Skip to content

Commit

Permalink
feat!: update auto import and styles vite plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
userquin committed Aug 27, 2024
1 parent 7487b50 commit 18fabcb
Show file tree
Hide file tree
Showing 11 changed files with 520 additions and 943 deletions.
10 changes: 6 additions & 4 deletions modern-sass-compiler/assets/main.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
@use 'vuetify' with (
$utilities: false,
$color-pack: false,
);
.gradient {
&.primary {
background: linear-gradient(to top right, #2563eb, #4b8efb);
color: white;
}
}
5 changes: 2 additions & 3 deletions modern-sass-compiler/assets/settings.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/* DON'T USE @use here */
@forward 'vuetify/settings' with (
@use 'vuetify/settings' with (
/*$utilities: false,*/
$button-height: 40px,
$button-border-radius: 8px
);
8 changes: 4 additions & 4 deletions modern-sass-compiler/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export default defineNuxtConfig({
compatibilityDate: '2024-08-15',
ssr: true,
sourcemap: true,
imports: {
autoImport: true,
Expand All @@ -16,7 +17,8 @@ export default defineNuxtConfig({
},
viewportSize: true,
},
// styles: { configFile: 'assets/settings.scss' },
// styles: 'sass',
styles: { configFile: 'assets/settings.scss' },
},
},
vite: {
Expand Down Expand Up @@ -51,12 +53,10 @@ export default defineNuxtConfig({
],
},
},
/*
css: ['~/assets/main.scss'],
*/
features: {
devLogs: false,
// inlineStyles: false,
inlineStyles: false,
},
experimental: {
payloadExtraction: false,
Expand Down
1 change: 0 additions & 1 deletion modern-sass-compiler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
"@nuxt/devtools": "latest",
"@unocss/nuxt": "^0.62.1",
"nuxt": "^3.12.4",
"sass": "^1.77.8",
"sass-embedded": "^1.77.8",
"typescript": "^5.5.4",
"vue-tsc": "^2.0.29",
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "vuetify-nuxt-module",
"type": "module",
"version": "0.17.1",
"packageManager": "pnpm@9.7.1",
"packageManager": "pnpm@9.9.0",
"description": "Zero-Config Nuxt Module for Vuetify",
"author": "userquin <[email protected]>",
"license": "MIT",
Expand Down Expand Up @@ -73,7 +73,8 @@
"perfect-debounce": "^1.0.0",
"ufo": "^1.5.4",
"unconfig": "^0.5.5",
"vite-plugin-vuetify": "^2.0.3",
"upath": "^2.0.1",
"vite-plugin-vuetify": "^2.0.4",
"vuetify": "^3.7.0"
},
"devDependencies": {
Expand Down
1,257 changes: 392 additions & 865 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { getPackageInfo } from 'local-pkg'
import type { HookResult } from '@nuxt/schema'
import type { VuetifyOptions, createVuetify } from 'vuetify'
import { version as VITE_VERSION } from 'vite'
import { version } from '../package.json'
import type {
InlineModuleOptions,
Expand Down Expand Up @@ -62,6 +63,10 @@ export default defineNuxtModule<VuetifyModuleOptions>({
&& versions.length > 1
&& (versions[0] > 3 || (versions[0] === 3 && versions[1] >= 5))

const viteVersion = VITE_VERSION.split('.')
.map((v: string) => v.includes('-') ? v.split('-')[0] : v)
.map(v => Number.parseInt(v)) as VuetifyNuxtContext['viteVersion']

const ctx: VuetifyNuxtContext = {
logger,
resolver: createResolver(import.meta.url),
Expand All @@ -79,6 +84,7 @@ export default defineNuxtModule<VuetifyModuleOptions>({
labComponentsPromise: undefined!,
vuetify3_4,
vuetify3_5,
viteVersion,
}

await load(options, nuxt, ctx)
Expand Down
1 change: 1 addition & 0 deletions src/utils/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface VuetifyNuxtContext {
labComponentsPromise: Promise<VuetifyComponentsImportMap>
vuetify3_4?: boolean
vuetify3_5?: boolean
viteVersion: [major: number, minor: number, patch: number]
}

export async function loadVuetifyConfiguration<U extends ExternalVuetifyOptions>(
Expand Down
37 changes: 25 additions & 12 deletions src/utils/configure-vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,30 @@ export function configureVite(configKey: string, nuxt: Nuxt, ctx: VuetifyNuxtCon
}

if (!ctx.moduleOptions.disableModernSassCompiler) {
viteInlineConfig.css ??= {}
viteInlineConfig.css.preprocessorOptions ??= {}
viteInlineConfig.css.preprocessorOptions.sass ??= {}
const sassEmbedded = isPackageExists('sass-embedded')
if (sassEmbedded) {
viteInlineConfig.css.preprocessorOptions.sass.api = 'modern-compiler'
}
else {
viteInlineConfig.css.preprocessorOptions.sass.api = 'modern'
if (!('preprocessorMaxWorkers' in viteInlineConfig.css))
viteInlineConfig.css.preprocessorMaxWorkers = true
// vite version >= 5.4.0
const [major, minor, patch] = ctx.viteVersion
const enableModernSassCompiler = major > 5 || (major === 5 && minor >= 4)
if (enableModernSassCompiler) {
const sassEmbedded = isPackageExists('sass-embedded')
if (sassEmbedded) {
// vite version >= 5.4.2
// check https://github.com/vitejs/vite/pull/17754 and https://github.com/vitejs/vite/pull/17728
const omit = major > 5 || (major === 5 && minor > 4) || (major === 5 && minor === 4 && patch >= 2)
if (!omit) {
viteInlineConfig.css ??= {}
viteInlineConfig.css.preprocessorOptions ??= {}
viteInlineConfig.css.preprocessorOptions.sass ??= {}
viteInlineConfig.css.preprocessorOptions.sass.api = 'modern-compiler'
}
}
else {
viteInlineConfig.css ??= {}
viteInlineConfig.css.preprocessorOptions ??= {}
viteInlineConfig.css.preprocessorOptions.sass ??= {}
viteInlineConfig.css.preprocessorOptions.sass.api = 'modern'
if (!('preprocessorMaxWorkers' in viteInlineConfig.css))
viteInlineConfig.css.preprocessorMaxWorkers = true
}
}
}

Expand All @@ -69,7 +82,7 @@ export function configureVite(configKey: string, nuxt: Nuxt, ctx: VuetifyNuxtCon
}

viteInlineConfig.plugins.push(vuetifyImportPlugin(vuetifyImportOptions))
viteInlineConfig.plugins.push(vuetifyStylesPlugin({ styles: ctx.moduleOptions.styles }, ctx.logger))
viteInlineConfig.plugins.push(vuetifyStylesPlugin({ styles: ctx.moduleOptions.styles }, ctx.viteVersion, ctx.logger))
viteInlineConfig.plugins.push(vuetifyConfigurationPlugin(ctx))
viteInlineConfig.plugins.push(vuetifyIconsPlugin(ctx))
viteInlineConfig.plugins.push(vuetifyDateConfigurationPlugin(ctx))
Expand Down
21 changes: 16 additions & 5 deletions src/vite/vuetify-import-plugin.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { extname } from 'node:path'
import { pathToFileURL } from 'node:url'
import type { Plugin } from 'vite'
import { createFilter } from 'vite'
import type { Options } from '@vuetify/loader-shared'
import { generateImports } from '@vuetify/loader-shared'
import { parseQuery, parseURL } from 'ufo'
Expand All @@ -24,19 +24,30 @@ function parseId(id: string) {
}

export function vuetifyImportPlugin(options: Options) {
let filter: (id: unknown) => boolean
return <Plugin>{
name: 'vuetify:import:nuxt',
configResolved(config) {
if (config.plugins.findIndex(plugin => plugin.name === 'vuetify:import') > -1)
throw new Error('Remove vite-plugin-vuetify from your Nuxt config file, this module registers a modified version.')

const vueIdx = config.plugins.findIndex(plugin => plugin.name === 'vite:vue')
const vueOptions = vueIdx > -1 ? config.plugins[vueIdx].api?.options : {}
filter = createFilter(vueOptions.include, vueOptions.exclude)
},
async transform(code, id) {
const { query, path } = parseId(id)

if (
((!query || !('vue' in query)) && extname(path) === '.vue' && !/^import { render as _sfc_render } from ".*"$/m.test(code))
|| (query && 'vue' in query && (query.type === 'template' || (query.type === 'script' && query.setup === 'true')))
) {
const isVueVirtual = query && 'vue' in query
const isVueFile = !isVueVirtual
&& filter(path)
&& !/^import { render as _sfc_render } from ".*"$/m.test(code)
const isVueTemplate = isVueVirtual && (
query.type === 'template'
|| (query.type === 'script' && query.setup === 'true')
)

if (isVueFile || isVueTemplate) {
const { code: imports, source } = generateImports(code, options)
return {
code: source + imports,
Expand Down
112 changes: 65 additions & 47 deletions src/vite/vuetify-styles-plugin.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
import process from 'node:process'
import { pathToFileURL } from 'node:url'
import type { Plugin } from 'vite'
import { normalizePath, resolveVuetifyBase } from '@vuetify/loader-shared'
import { isAbsolute, join, relative as relativePath } from 'pathe'
import { isObject, normalizePath, resolveVuetifyBase } from '@vuetify/loader-shared'
import { isAbsolute, relative as relativePath } from 'pathe'
import type { Options } from '@vuetify/loader-shared'

function isSubdir(root: string, test: string) {
const relative = relativePath(root, test)
return relative && !relative.startsWith('..') && !isAbsolute(relative)
}
import path from 'upath'
import type { VuetifyNuxtContext } from '../utils/config'

export function vuetifyStylesPlugin(
options: Options,
[major, minor, patch]: VuetifyNuxtContext['viteVersion'],
_logger: ReturnType<typeof import('@nuxt/kit')['useLogger']>,
) {
let configFile: string | undefined
// let cacheDir: string | undefined
const vuetifyBase = resolveVuetifyBase()

let configFile: string
const tempFiles = new Map<string, string>()
const noneFiles = new Set<string>()
let isNone = false
let sassVariables = false
let fileImport = false
const PREFIX = 'vuetify-styles/'
const SSR_PREFIX = `/@${PREFIX}`

return <Plugin>{
name: 'vuetify:styles:nuxt',
Expand All @@ -25,64 +29,78 @@ export function vuetifyStylesPlugin(
if (config.plugins.findIndex(plugin => plugin.name === 'vuetify:styles') > -1)
throw new Error('Remove vite-plugin-vuetify from your Nuxt config file, this module registers a modified version.')

if (typeof options.styles === 'object') {
if (isAbsolute(options.styles.configFile))
configFile = options.styles.configFile
if (isObject(options.styles)) {
sassVariables = true
// use file import when vite version > 5.4.2
// check https://github.com/vitejs/vite/pull/17909
fileImport = major > 5 || (major === 5 && minor > 4) || (major === 5 && minor === 4 && patch > 2)
if (path.isAbsolute(options.styles.configFile))
configFile = path.resolve(options.styles.configFile)
else
configFile = join(config.root || process.cwd(), options.styles.configFile)
configFile = path.resolve(path.join(config.root || process.cwd(), options.styles.configFile))

configFile = fileImport
? pathToFileURL(configFile).href
: normalizePath(configFile)
}
else {
isNone = options.styles === 'none'
}
},
async resolveId(source, importer, { custom, ssr }) {
if (source.startsWith(PREFIX) || source.startsWith(SSR_PREFIX))
return source

if (
source === 'vuetify/styles' || (
importer
&& source.endsWith('.css')
&& isSubdir(vuetifyBase, isAbsolute(source) ? source : importer)
&& isSubdir(vuetifyBase, path.isAbsolute(source) ? source : importer)
)
) {
if (options.styles === 'none') {
return '/@plugin-vuetify/lib/__void__'
}
else if (options.styles === 'sass') {
if (options.styles === 'sass') {
const target = source.replace(/\.css$/, '.sass')
return this.resolve(target, importer, { skipSelf: true, custom })
}
else if (typeof options.styles === 'object') {
const resolution = await this.resolve(source, importer, { skipSelf: true, custom })

if (!resolution)
return null

const target = resolution.id.replace(/\.css$/, '.sass')
const file = relativePath(join(vuetifyBase, 'lib'), target)
const contents = `@use "${normalizePath(configFile)}"\n@use "${normalizePath(target)}"`

tempFiles.set(file, contents)
const resolution = await this.resolve(source, importer, { skipSelf: true, custom })
if (!resolution)
return undefined

return ssr
? `/@plugin-vuetify/lib/${file}`
: `/@fs/plugin-vuetify/lib/${file}`
const target = resolution.id.replace(/\.css$/, '.sass')
if (isNone) {
noneFiles.add(target)
return target
}

return `${ssr ? SSR_PREFIX : PREFIX}${path.relative(vuetifyBase, target)}`
}

return undefined
},
load(id) {
// When Vite is configured with `optimizeDeps.exclude: ['vuetify']`, the
// received id contains a version hash (e.g. \0__void__?v=893fa859).
if (/^\/@plugin-vuetify\/lib\/__void__(\?.*)?$/.test(id))
return ''

if (id.startsWith('/@plugin-vuetify/lib/')) {
const file = /^\/@plugin-vuetify\/lib\/(.*?)(\?.*)?$/.exec(id)![1]
return tempFiles.get(file)
}
if (sassVariables) {
const target = id.startsWith(PREFIX)
? path.resolve(vuetifyBase, id.slice(PREFIX.length))
: id.startsWith(SSR_PREFIX)
? path.resolve(vuetifyBase, id.slice(SSR_PREFIX.length))
: undefined

if (id.startsWith('/@fs/plugin-vuetify/lib/')) {
const file = /^\/@fs\/plugin-vuetify\/lib\/(.*?)(\?.*)?$/.exec(id)![1]
return tempFiles.get(file)
if (target) {
return {
code: `@use "${configFile}"\n@use "${fileImport ? pathToFileURL(target).href : normalizePath(target)}"`,
map: {
mappings: '',
},
}
}
}

if (id.includes('plugin-vuetify/lib'))
return ''
return isNone && noneFiles.has(id) ? '' : undefined
},
}
}

function isSubdir(root: string, test: string) {
const relative = relativePath(root, test)
return relative && !relative.startsWith('..') && !isAbsolute(relative)
}

0 comments on commit 18fabcb

Please sign in to comment.