mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-11 08:33:53 +00:00
refactor(schema,webpack)!: split out webpack and postcss build options (#2812)
* refactor: split out webpack and postcss build options * feat(schema): set nuxt3 builder in config * fix(schema): default postcss config file to false * chore: update lockfile * style: remove unused imports * refactor(webpack): remove (previously disabled) babel config * refactor: move shared vite options into schema * fix(schema): omit __NUXT_BASE__ from defaults * fix: move appDir-dependent options back to vite * refactor: split out virtual modules * refactor: extract compile/createDevMiddleware * refactor: further improvements * chore: remove `@nuxt/webpack-builder` dependency * chore: update lockfile * refactor: move `builder` option to top level * fix: bind close to watcher instance * chore: update lockfile * fix: create portal between postcss & build.postcss.postcssOptions * fix: remove duplicate * fix: revert * fix: use `postcss` directly * fix: import builder from rootDir * chore: dedupe webpack install * test: update fixture to use `builder` * fix: bind class in pify Co-authored-by: Pooya Parsa <pyapar@gmail.com>
This commit is contained in:
parent
2b3dbed594
commit
73ba30fb69
@ -83,6 +83,10 @@ export function useModuleContainer (nuxt: Nuxt = useNuxt()): ModuleContainer {
|
|||||||
extendBuild (fn) {
|
extendBuild (fn) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
nuxt.options.build.extend = chainFn(nuxt.options.build.extend, fn)
|
nuxt.options.build.extend = chainFn(nuxt.options.build.extend, fn)
|
||||||
|
|
||||||
|
if (!isNuxt2(nuxt)) {
|
||||||
|
console.warn('[kit] [compat] Using `extendBuild` in Nuxt 3 has no effect. Instead call extendWebpackConfig and extendViteConfig.')
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
extendRoutes (fn) {
|
extendRoutes (fn) {
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
"@nuxt/nitro": "3.0.0",
|
"@nuxt/nitro": "3.0.0",
|
||||||
"@nuxt/schema": "3.0.0",
|
"@nuxt/schema": "3.0.0",
|
||||||
"@nuxt/vite-builder": "3.0.0",
|
"@nuxt/vite-builder": "3.0.0",
|
||||||
"@nuxt/webpack-builder": "3.0.0",
|
|
||||||
"@vue/reactivity": "^3.2.31",
|
"@vue/reactivity": "^3.2.31",
|
||||||
"@vue/shared": "^3.2.31",
|
"@vue/shared": "^3.2.31",
|
||||||
"@vueuse/head": "^0.7.5",
|
"@vueuse/head": "^0.7.5",
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import chokidar from 'chokidar'
|
import chokidar from 'chokidar'
|
||||||
import type { Nuxt } from '@nuxt/schema'
|
import type { Nuxt } from '@nuxt/schema'
|
||||||
|
import { tryImportModule } from '@nuxt/kit'
|
||||||
import { createApp, generateApp } from './app'
|
import { createApp, generateApp } from './app'
|
||||||
|
|
||||||
export async function build (nuxt: Nuxt) {
|
export async function build (nuxt: Nuxt) {
|
||||||
@ -48,8 +49,9 @@ function watch (nuxt: Nuxt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function bundle (nuxt: Nuxt) {
|
async function bundle (nuxt: Nuxt) {
|
||||||
const useVite = nuxt.options.vite !== false
|
const { bundle } = typeof nuxt.options.builder === 'string'
|
||||||
const { bundle } = await (useVite ? import('@nuxt/vite-builder') : import('@nuxt/webpack-builder'))
|
? await tryImportModule(nuxt.options.builder, { paths: nuxt.options.rootDir })
|
||||||
|
: nuxt.options.builder
|
||||||
try {
|
try {
|
||||||
return bundle(nuxt)
|
return bundle(nuxt)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -9,7 +9,10 @@ export default defineBuildConfig({
|
|||||||
name: 'config',
|
name: 'config',
|
||||||
builder: 'untyped',
|
builder: 'untyped',
|
||||||
defaults: {
|
defaults: {
|
||||||
rootDir: '/<rootDir>/'
|
rootDir: '/<rootDir>/',
|
||||||
|
vite: {
|
||||||
|
base: '/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'src/index'
|
'src/index'
|
||||||
@ -24,6 +27,12 @@ export default defineBuildConfig({
|
|||||||
'webpack-bundle-analyzer',
|
'webpack-bundle-analyzer',
|
||||||
'rollup-plugin-visualizer',
|
'rollup-plugin-visualizer',
|
||||||
'vite',
|
'vite',
|
||||||
|
'mini-css-extract-plugin',
|
||||||
|
'terser-webpack-plugin',
|
||||||
|
'css-minimizer-webpack-plugin',
|
||||||
|
'webpack-dev-middleware',
|
||||||
|
'webpack-hot-middleware',
|
||||||
|
'postcss',
|
||||||
'consola',
|
'consola',
|
||||||
// Implicit
|
// Implicit
|
||||||
'@vue/compiler-core',
|
'@vue/compiler-core',
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
"defu": "^5.0.1",
|
"defu": "^5.0.1",
|
||||||
"jiti": "^1.13.0",
|
"jiti": "^1.13.0",
|
||||||
"pathe": "^0.2.0",
|
"pathe": "^0.2.0",
|
||||||
|
"postcss-import-resolver": "^2.0.0",
|
||||||
"scule": "^0.2.1",
|
"scule": "^0.2.1",
|
||||||
"std-env": "^3.0.1",
|
"std-env": "^3.0.1",
|
||||||
"ufo": "^0.7.9"
|
"ufo": "^0.7.9"
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -10,7 +10,10 @@ import router from './router'
|
|||||||
import server from './server'
|
import server from './server'
|
||||||
import cli from './cli'
|
import cli from './cli'
|
||||||
import generate from './generate'
|
import generate from './generate'
|
||||||
|
import postcss from './postcss'
|
||||||
import typescript from './typescript'
|
import typescript from './typescript'
|
||||||
|
import vite from './vite'
|
||||||
|
import webpack from './webpack'
|
||||||
import nitro from './nitro'
|
import nitro from './nitro'
|
||||||
import experimental from './experimental'
|
import experimental from './experimental'
|
||||||
|
|
||||||
@ -37,25 +40,18 @@ export default {
|
|||||||
..._app,
|
..._app,
|
||||||
..._common,
|
..._common,
|
||||||
..._internal,
|
..._internal,
|
||||||
|
...postcss,
|
||||||
|
...typescript,
|
||||||
|
...vite,
|
||||||
|
...webpack,
|
||||||
...nitro,
|
...nitro,
|
||||||
build,
|
// Legacy
|
||||||
|
...build,
|
||||||
messages,
|
messages,
|
||||||
render,
|
render,
|
||||||
router,
|
router,
|
||||||
server,
|
server,
|
||||||
cli,
|
cli,
|
||||||
generate,
|
generate,
|
||||||
typescript,
|
|
||||||
experimental,
|
experimental,
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration that will be passed directly to Vite.
|
|
||||||
*
|
|
||||||
* See https://vitejs.dev/config for more information.
|
|
||||||
* Please note that not all vite options are supported in Nuxt.
|
|
||||||
*
|
|
||||||
* @type {boolean | typeof import('vite').InlineConfig}
|
|
||||||
* @version 3
|
|
||||||
*/
|
|
||||||
vite: undefined,
|
|
||||||
}
|
}
|
||||||
|
53
packages/schema/src/config/postcss.ts
Normal file
53
packages/schema/src/config/postcss.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import defu from 'defu'
|
||||||
|
import createResolver from 'postcss-import-resolver'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
/** @version 3 */
|
||||||
|
postcss: {
|
||||||
|
/** Path to postcss config file. */
|
||||||
|
/** @type string | false */
|
||||||
|
config: false,
|
||||||
|
/**
|
||||||
|
* Options for configuring PostCSS plugins.
|
||||||
|
*
|
||||||
|
* https://postcss.org/
|
||||||
|
*/
|
||||||
|
plugins: {
|
||||||
|
/**
|
||||||
|
* https://github.com/postcss/postcss-import
|
||||||
|
*/
|
||||||
|
'postcss-import': {
|
||||||
|
$resolve: (val, get) => val !== false ? defu(val || {}, {
|
||||||
|
resolve: createResolver({
|
||||||
|
alias: { ...get('alias') },
|
||||||
|
modules: [
|
||||||
|
get('srcDir'),
|
||||||
|
get('rootDir'),
|
||||||
|
...get('modulesDir')
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}) : val,
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://github.com/postcss/postcss-url
|
||||||
|
*/
|
||||||
|
'postcss-url': {},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://github.com/postcss/autoprefixer
|
||||||
|
*/
|
||||||
|
autoprefixer: {},
|
||||||
|
|
||||||
|
cssnano: {
|
||||||
|
$resolve: (val, get) => val ?? (get('dev') && {
|
||||||
|
preset: ['default', {
|
||||||
|
// Keep quotes in font values to prevent from HEX conversion
|
||||||
|
// https://github.com/nuxt/nuxt.js/issues/6306
|
||||||
|
minifyFontValues: { removeQuotes: false }
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,21 +1,23 @@
|
|||||||
export default {
|
export default {
|
||||||
/**
|
typescript: {
|
||||||
|
/**
|
||||||
* TypeScript comes with certain checks to give you more safety and analysis of your program.
|
* TypeScript comes with certain checks to give you more safety and analysis of your program.
|
||||||
* Once you’ve converted your codebase to TypeScript, you can start enabling these checks for greater safety.
|
* Once you’ve converted your codebase to TypeScript, you can start enabling these checks for greater safety.
|
||||||
* [Read More](https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html#getting-stricter-checks)
|
* [Read More](https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html#getting-stricter-checks)
|
||||||
*/
|
*/
|
||||||
strict: false,
|
strict: false,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* You can extend generated `.nuxt/tsconfig.json` using this option
|
* You can extend generated `.nuxt/tsconfig.json` using this option
|
||||||
* @typedef {Awaited<ReturnType<typeof import('pkg-types')['readPackageJSON']>>}
|
* @typedef {Awaited<ReturnType<typeof import('pkg-types')['readPackageJSON']>>}
|
||||||
*/
|
*/
|
||||||
tsConfig: {},
|
tsConfig: {},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a `*.vue` shim.
|
* Generate a `*.vue` shim.
|
||||||
*
|
*
|
||||||
* We recommend instead either enabling [**Take Over Mode**](https://github.com/johnsoncodehk/volar/discussions/471) or adding **TypeScript Vue Plugin (Volar)** 👉 [[Download](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.vscode-typescript-vue-plugin)].
|
* We recommend instead either enabling [**Take Over Mode**](https://github.com/johnsoncodehk/volar/discussions/471) or adding **TypeScript Vue Plugin (Volar)** 👉 [[Download](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.vscode-typescript-vue-plugin)].
|
||||||
*/
|
*/
|
||||||
shim: true
|
shim: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
83
packages/schema/src/config/vite.ts
Normal file
83
packages/schema/src/config/vite.ts
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import { resolve } from 'pathe'
|
||||||
|
import { joinURL, withoutLeadingSlash } from 'ufo'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
/**
|
||||||
|
* Configuration that will be passed directly to Vite.
|
||||||
|
*
|
||||||
|
* See https://vitejs.dev/config for more information.
|
||||||
|
* Please note that not all vite options are supported in Nuxt.
|
||||||
|
*
|
||||||
|
* @type {typeof import('vite').InlineConfig}
|
||||||
|
* @version 3
|
||||||
|
*/
|
||||||
|
vite: {
|
||||||
|
root: {
|
||||||
|
$resolve: (val, get) => val ?? get('srcDir'),
|
||||||
|
},
|
||||||
|
mode: {
|
||||||
|
$resolve: (val, get) => val ?? get('dev') ? 'development' : 'production',
|
||||||
|
},
|
||||||
|
logLevel: 'warn',
|
||||||
|
define: {
|
||||||
|
$resolve: (val, get) => ({
|
||||||
|
'process.dev': get('dev'),
|
||||||
|
...val || {}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
|
||||||
|
},
|
||||||
|
base: {
|
||||||
|
$resolve: (val, get) => val ?? get('dev')
|
||||||
|
? joinURL(get('app').baseURL, get('app').buildAssetsDir)
|
||||||
|
: '/__NUXT_BASE__/',
|
||||||
|
},
|
||||||
|
publicDir: {
|
||||||
|
$resolve: (val, get) => val ?? resolve(get('srcDir'), get('dir').public),
|
||||||
|
},
|
||||||
|
vue: {
|
||||||
|
isProduction: {
|
||||||
|
$resolve: (val, get) => val ?? !get('dev'),
|
||||||
|
},
|
||||||
|
template: { compilerOptions: {
|
||||||
|
$resolve: (val, get) => val ?? get('vue').compilerOptions }
|
||||||
|
},
|
||||||
|
},
|
||||||
|
optimizeDeps: {
|
||||||
|
exclude: {
|
||||||
|
$resolve: (val, get) => [
|
||||||
|
...val || [],
|
||||||
|
...get('build.transpile').filter(i => typeof i === 'string'),
|
||||||
|
'vue-demi'
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
esbuild: {
|
||||||
|
jsxFactory: 'h',
|
||||||
|
jsxFragment: 'Fragment',
|
||||||
|
tsconfigRaw: '{}'
|
||||||
|
},
|
||||||
|
clearScreen: false,
|
||||||
|
build: {
|
||||||
|
assetsDir: {
|
||||||
|
$resolve: (val, get) => val ?? get('dev') ? withoutLeadingSlash(get('app').buildAssetsDir) : '.',
|
||||||
|
},
|
||||||
|
emptyOutDir: false,
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
fs: {
|
||||||
|
strict: false,
|
||||||
|
allow: {
|
||||||
|
$resolve: (val, get) => [
|
||||||
|
get('buildDir'),
|
||||||
|
get('srcDir'),
|
||||||
|
get('rootDir'),
|
||||||
|
...get('modulesDir'),
|
||||||
|
...val ?? []
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
294
packages/schema/src/config/webpack.ts
Normal file
294
packages/schema/src/config/webpack.ts
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
import { join } from 'pathe'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
/** @version 3 */
|
||||||
|
webpack: {
|
||||||
|
/**
|
||||||
|
* Nuxt uses `webpack-bundle-analyzer` to visualize your bundles and how to optimize them.
|
||||||
|
*
|
||||||
|
* Set to `true` to enable bundle analysis, or pass an object with options: [for webpack](https://github.com/webpack-contrib/webpack-bundle-analyzer#options-for-plugin) or [for vite](https://github.com/btd/rollup-plugin-visualizer#options).
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```js
|
||||||
|
* analyze: {
|
||||||
|
* analyzerMode: 'static'
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @type {boolean | typeof import('webpack-bundle-analyzer').BundleAnalyzerPlugin.Options}
|
||||||
|
*/
|
||||||
|
analyze: {
|
||||||
|
$resolve: (val, get) => {
|
||||||
|
if(val !== true) {
|
||||||
|
return val ?? false
|
||||||
|
}
|
||||||
|
const rootDir = get('rootDir')
|
||||||
|
return {
|
||||||
|
template: 'treemap',
|
||||||
|
projectRoot: rootDir,
|
||||||
|
filename: join(rootDir, '.nuxt/stats', '{name}.html')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable the profiler in webpackbar.
|
||||||
|
*
|
||||||
|
* It is normally enabled by CLI argument `--profile`.
|
||||||
|
*
|
||||||
|
* @see [webpackbar](https://github.com/unjs/webpackbar#profile)
|
||||||
|
*/
|
||||||
|
profile: process.argv.includes('--profile'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables Common CSS Extraction using
|
||||||
|
* [Vue Server Renderer guidelines](https://ssr.vuejs.org/guide/css.html).
|
||||||
|
*
|
||||||
|
* Using [extract-css-chunks-webpack-plugin](https://github.com/faceyspacey/extract-css-chunks-webpack-plugin/) under the hood, your CSS will be extracted
|
||||||
|
* into separate files, usually one per component. This allows caching your CSS and
|
||||||
|
* JavaScript separately and is worth trying if you have a lot of global or shared CSS.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```js
|
||||||
|
* export default {
|
||||||
|
* build: {
|
||||||
|
* extractCSS: true,
|
||||||
|
* // or
|
||||||
|
* extractCSS: {
|
||||||
|
* ignoreOrder: true
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If you want to extract all your CSS to a single file, there is a workaround for this.
|
||||||
|
* However, note that it is not recommended to extract everything into a single file.
|
||||||
|
* Extracting into multiple CSS files is better for caching and preload isolation. It
|
||||||
|
* can also improve page performance by downloading and resolving only those resources
|
||||||
|
* that are needed.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```js
|
||||||
|
* export default {
|
||||||
|
* build: {
|
||||||
|
* extractCSS: true,
|
||||||
|
* optimization: {
|
||||||
|
* splitChunks: {
|
||||||
|
* cacheGroups: {
|
||||||
|
* styles: {
|
||||||
|
* name: 'styles',
|
||||||
|
* test: /\.(css|vue)$/,
|
||||||
|
* chunks: 'all',
|
||||||
|
* enforce: true
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @type {false | typeof import('mini-css-extract-plugin').PluginOptions}
|
||||||
|
*/
|
||||||
|
extractCSS: false,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables CSS source map support (defaults to true in development)
|
||||||
|
*/
|
||||||
|
cssSourceMap: {
|
||||||
|
$resolve: (val, get) => val ?? get('dev')
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The polyfill library to load to provide URL and URLSearchParams.
|
||||||
|
*
|
||||||
|
* Defaults to `'url'` ([see package](https://www.npmjs.com/package/url)).
|
||||||
|
*/
|
||||||
|
serverURLPolyfill: 'url',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customize bundle filenames.
|
||||||
|
*
|
||||||
|
* To understand a bit more about the use of manifests, take a look at [this webpack documentation](https://webpack.js.org/guides/code-splitting/).
|
||||||
|
*
|
||||||
|
* @note Be careful when using non-hashed based filenames in production
|
||||||
|
* as most browsers will cache the asset and not detect the changes on first load.
|
||||||
|
*
|
||||||
|
* This example changes fancy chunk names to numerical ids:
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```js
|
||||||
|
* filenames: {
|
||||||
|
* chunk: ({ isDev }) => (isDev ? '[name].js' : '[id].[contenthash].js')
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
filenames: {
|
||||||
|
app: ({ isDev }) => isDev ? `[name].js` : `[contenthash:7].js`,
|
||||||
|
chunk: ({ isDev }) => isDev ? `[name].js` : `[contenthash:7].js`,
|
||||||
|
css: ({ isDev }) => isDev ? '[name].css' : 'css/[contenthash:7].css',
|
||||||
|
img: ({ isDev }) => isDev ? '[path][name].[ext]' : 'img/[name].[contenthash:7].[ext]',
|
||||||
|
font: ({ isDev }) => isDev ? '[path][name].[ext]' : 'fonts/[name].[contenthash:7].[ext]',
|
||||||
|
video: ({ isDev }) => isDev ? '[path][name].[ext]' : 'videos/[name].[contenthash:7].[ext]'
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customize the options of Nuxt's integrated webpack loaders.
|
||||||
|
*/
|
||||||
|
loaders: {
|
||||||
|
$resolve: (val, get) => {
|
||||||
|
const styleLoaders = [
|
||||||
|
'css', 'cssModules', 'less',
|
||||||
|
'sass', 'scss', 'stylus', 'vueStyle'
|
||||||
|
]
|
||||||
|
for (const name of styleLoaders) {
|
||||||
|
const loader = val[name]
|
||||||
|
if (loader && loader.sourceMap === undefined) {
|
||||||
|
loader.sourceMap = Boolean(get('build.cssSourceMap'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
},
|
||||||
|
file: { esModule: false },
|
||||||
|
fontUrl: { esModule: false, limit: 1000 },
|
||||||
|
imgUrl: { esModule: false, limit: 1000 },
|
||||||
|
pugPlain: {},
|
||||||
|
vue: {
|
||||||
|
productionMode: { $resolve: (val, get) => val ?? !get('dev') },
|
||||||
|
transformAssetUrls: {
|
||||||
|
video: 'src',
|
||||||
|
source: 'src',
|
||||||
|
object: 'src',
|
||||||
|
embed: 'src'
|
||||||
|
},
|
||||||
|
compilerOptions: { $resolve: (val, get) => val ?? get('vue.compilerOptions') },
|
||||||
|
},
|
||||||
|
css: {
|
||||||
|
importLoaders: 0,
|
||||||
|
esModule: false
|
||||||
|
},
|
||||||
|
cssModules: {
|
||||||
|
importLoaders: 0,
|
||||||
|
esModule: false,
|
||||||
|
modules: {
|
||||||
|
localIdentName: '[local]_[hash:base64:5]'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
less: {},
|
||||||
|
sass: {
|
||||||
|
sassOptions: {
|
||||||
|
indentedSyntax: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scss: {},
|
||||||
|
stylus: {},
|
||||||
|
vueStyle: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add webpack plugins.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```js
|
||||||
|
* import webpack from 'webpack'
|
||||||
|
* import { version } from './package.json'
|
||||||
|
* // ...
|
||||||
|
* plugins: [
|
||||||
|
* new webpack.DefinePlugin({
|
||||||
|
* 'process.VERSION': version
|
||||||
|
* })
|
||||||
|
* ]
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
plugins: [],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Terser plugin options.
|
||||||
|
*
|
||||||
|
* Set to false to disable this plugin, or pass an object of options.
|
||||||
|
*
|
||||||
|
* @see [terser-webpack-plugin documentation](https://github.com/webpack-contrib/terser-webpack-plugin)
|
||||||
|
*
|
||||||
|
* @note Enabling sourceMap will leave `//# sourceMappingURL` linking comment at
|
||||||
|
* the end of each output file if webpack `config.devtool` is set to `source-map`.
|
||||||
|
*
|
||||||
|
* @type {false | typeof import('terser-webpack-plugin').BasePluginOptions & typeof import('terser-webpack-plugin').DefinedDefaultMinimizerAndOptions<any>}
|
||||||
|
*/
|
||||||
|
terser: {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hard-replaces `typeof process`, `typeof window` and `typeof document` to tree-shake bundle.
|
||||||
|
*/
|
||||||
|
aggressiveCodeRemoval: false,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OptimizeCSSAssets plugin options.
|
||||||
|
*
|
||||||
|
* Defaults to true when `extractCSS` is enabled.
|
||||||
|
*
|
||||||
|
* @see [css-minimizer-webpack-plugin documentation](https://github.com/webpack-contrib/css-minimizer-webpack-plugin).
|
||||||
|
*
|
||||||
|
* @type {false | typeof import('css-minimizer-webpack-plugin').BasePluginOptions & typeof import('css-minimizer-webpack-plugin').DefinedDefaultMinimizerAndOptions<any>}
|
||||||
|
*/
|
||||||
|
optimizeCSS: {
|
||||||
|
$resolve: (val, get) => val ?? (get('build.extractCSS') ? {} : false)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure [webpack optimization](https://webpack.js.org/configuration/optimization/).
|
||||||
|
* @type {false | typeof import('webpack').Configuration['optimization']}
|
||||||
|
*/
|
||||||
|
optimization: {
|
||||||
|
runtimeChunk: 'single',
|
||||||
|
/** Set minimize to false to disable all minimizers. (It is disabled in development by default) */
|
||||||
|
minimize: { $resolve: (val, get) => val ?? !get('dev') },
|
||||||
|
/** You can set minimizer to a customized array of plugins. */
|
||||||
|
minimizer: undefined,
|
||||||
|
splitChunks: {
|
||||||
|
chunks: 'all',
|
||||||
|
automaticNameDelimiter: '/',
|
||||||
|
cacheGroups: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Customize PostCSS Loader.
|
||||||
|
* Same options as https://github.com/webpack-contrib/postcss-loader#options
|
||||||
|
*/
|
||||||
|
postcss: {
|
||||||
|
execute: undefined,
|
||||||
|
postcssOptions: {
|
||||||
|
config: {
|
||||||
|
$resolve: (val, get) => val ?? get('postcss.config')
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
$resolve: (val, get) => val ?? get('postcss.plugins')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sourceMap: undefined,
|
||||||
|
implementation: undefined,
|
||||||
|
order: ''
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) for available options.
|
||||||
|
* @type {typeof import('webpack-dev-middleware').Options<typeof import('http').IncomingMessage, typeof import('http').ServerResponse>}
|
||||||
|
*/
|
||||||
|
devMiddleware: {
|
||||||
|
stats: 'none'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* See [webpack-hot-middleware](https://github.com/webpack-contrib/webpack-hot-middleware) for available options.
|
||||||
|
* @type {typeof import('webpack-hot-middleware').MiddlewareOptions & { client?: typeof import('webpack-hot-middleware').ClientOptions }}
|
||||||
|
*/
|
||||||
|
hotMiddleware: {},
|
||||||
|
/**
|
||||||
|
* Set to `false` to disable the overlay provided by [FriendlyErrorsWebpackPlugin](https://github.com/nuxt/friendly-errors-webpack-plugin)
|
||||||
|
*/
|
||||||
|
friendlyErrors: true,
|
||||||
|
/**
|
||||||
|
* Filters to hide build warnings.
|
||||||
|
* @type {Array<(warn: typeof import('webpack').WebpackError) => boolean>}
|
||||||
|
*/
|
||||||
|
warningIgnoreFilters: [],
|
||||||
|
}
|
||||||
|
}
|
@ -70,7 +70,7 @@ export interface ModuleContainer {
|
|||||||
/** Allows extending webpack build config by chaining `options.build.extend` function. */
|
/** Allows extending webpack build config by chaining `options.build.extend` function. */
|
||||||
extendBuild(fn): void
|
extendBuild(fn): void
|
||||||
|
|
||||||
/** Allows extending routes by chaining `options.build.extendRoutes` function. */
|
/** Allows extending routes by chaining `options.router.extendRoutes` function. */
|
||||||
extendRoutes(fn): void
|
extendRoutes(fn): void
|
||||||
|
|
||||||
/** Registers a module */
|
/** Registers a module */
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
"p-debounce": "^4.0.0",
|
"p-debounce": "^4.0.0",
|
||||||
"pathe": "^0.2.0",
|
"pathe": "^0.2.0",
|
||||||
"postcss-import": "^14.0.2",
|
"postcss-import": "^14.0.2",
|
||||||
"postcss-import-resolver": "^2.0.0",
|
|
||||||
"postcss-url": "^10.1.3",
|
"postcss-url": "^10.1.3",
|
||||||
"rollup-plugin-visualizer": "^5.6.0",
|
"rollup-plugin-visualizer": "^5.6.0",
|
||||||
"ufo": "^0.7.9",
|
"ufo": "^0.7.9",
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import createResolver from 'postcss-import-resolver'
|
|
||||||
import defu from 'defu'
|
|
||||||
import { requireModule } from '@nuxt/kit'
|
import { requireModule } from '@nuxt/kit'
|
||||||
import type { Nuxt } from '@nuxt/schema'
|
import type { Nuxt } from '@nuxt/schema'
|
||||||
import { ViteOptions } from './vite'
|
import type { ViteOptions } from './vite'
|
||||||
import { distDir } from './dirs'
|
import { distDir } from './dirs'
|
||||||
|
|
||||||
export function resolveCSSOptions (nuxt: Nuxt): ViteOptions['css'] {
|
export function resolveCSSOptions (nuxt: Nuxt): ViteOptions['css'] {
|
||||||
@ -12,25 +10,7 @@ export function resolveCSSOptions (nuxt: Nuxt): ViteOptions['css'] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const plugins = defu(nuxt.options.build.postcss.postcssOptions.plugins, {
|
const plugins = nuxt.options.postcss.plugins
|
||||||
// https://github.com/postcss/postcss-import
|
|
||||||
'postcss-import': {
|
|
||||||
resolve: createResolver({
|
|
||||||
alias: { ...nuxt.options.alias },
|
|
||||||
modules: [
|
|
||||||
nuxt.options.srcDir,
|
|
||||||
nuxt.options.rootDir,
|
|
||||||
...nuxt.options.modulesDir
|
|
||||||
]
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// https://github.com/postcss/postcss-url
|
|
||||||
'postcss-url': {},
|
|
||||||
|
|
||||||
// https://github.com/postcss/autoprefixer
|
|
||||||
autoprefixer: {}
|
|
||||||
})
|
|
||||||
|
|
||||||
for (const name in plugins) {
|
for (const name in plugins) {
|
||||||
const opts = plugins[name]
|
const opts = plugins[name]
|
||||||
|
@ -5,7 +5,6 @@ import type { InlineConfig, SSROptions } from 'vite'
|
|||||||
import { logger } from '@nuxt/kit'
|
import { logger } from '@nuxt/kit'
|
||||||
import type { Options } from '@vitejs/plugin-vue'
|
import type { Options } from '@vitejs/plugin-vue'
|
||||||
import { sanitizeFilePath } from 'mlly'
|
import { sanitizeFilePath } from 'mlly'
|
||||||
import { joinURL, withoutLeadingSlash } from 'ufo'
|
|
||||||
import { getPort } from 'get-port-please'
|
import { getPort } from 'get-port-please'
|
||||||
import { buildClient } from './client'
|
import { buildClient } from './client'
|
||||||
import { buildServer } from './server'
|
import { buildServer } from './server'
|
||||||
@ -35,14 +34,7 @@ export async function bundle (nuxt: Nuxt) {
|
|||||||
nuxt,
|
nuxt,
|
||||||
config: vite.mergeConfig(
|
config: vite.mergeConfig(
|
||||||
{
|
{
|
||||||
root: nuxt.options.srcDir,
|
|
||||||
mode: nuxt.options.dev ? 'development' : 'production',
|
|
||||||
logLevel: 'warn',
|
|
||||||
define: {
|
|
||||||
'process.dev': nuxt.options.dev
|
|
||||||
},
|
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
|
|
||||||
alias: {
|
alias: {
|
||||||
...nuxt.options.alias,
|
...nuxt.options.alias,
|
||||||
'#app': nuxt.options.appDir,
|
'#app': nuxt.options.appDir,
|
||||||
@ -56,37 +48,16 @@ export async function bundle (nuxt: Nuxt) {
|
|||||||
'abort-controller': 'unenv/runtime/mock/empty'
|
'abort-controller': 'unenv/runtime/mock/empty'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
base: nuxt.options.dev
|
|
||||||
? joinURL(nuxt.options.app.baseURL, nuxt.options.app.buildAssetsDir)
|
|
||||||
: '/__NUXT_BASE__/',
|
|
||||||
publicDir: resolve(nuxt.options.srcDir, nuxt.options.dir.public),
|
|
||||||
// TODO: move to kit schema when it exists
|
|
||||||
vue: {
|
|
||||||
isProduction: !nuxt.options.dev,
|
|
||||||
template: { compilerOptions: nuxt.options.vue.compilerOptions }
|
|
||||||
},
|
|
||||||
css: resolveCSSOptions(nuxt),
|
|
||||||
optimizeDeps: {
|
optimizeDeps: {
|
||||||
exclude: [
|
|
||||||
...nuxt.options.build.transpile.filter(i => typeof i === 'string'),
|
|
||||||
'vue-demi'
|
|
||||||
],
|
|
||||||
entries: [
|
entries: [
|
||||||
resolve(nuxt.options.appDir, 'entry.ts')
|
resolve(nuxt.options.appDir, 'entry.ts')
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
esbuild: {
|
css: resolveCSSOptions(nuxt),
|
||||||
jsxFactory: 'h',
|
|
||||||
jsxFragment: 'Fragment',
|
|
||||||
tsconfigRaw: '{}'
|
|
||||||
},
|
|
||||||
clearScreen: false,
|
|
||||||
build: {
|
build: {
|
||||||
assetsDir: nuxt.options.dev ? withoutLeadingSlash(nuxt.options.app.buildAssetsDir) : '.',
|
|
||||||
emptyOutDir: false,
|
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
input: resolve(nuxt.options.appDir, 'entry'),
|
output: { sanitizeFileName: sanitizeFilePath },
|
||||||
output: { sanitizeFileName: sanitizeFilePath }
|
input: resolve(nuxt.options.appDir, 'entry')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
@ -98,18 +69,13 @@ export async function bundle (nuxt: Nuxt) {
|
|||||||
port: hmrPort
|
port: hmrPort
|
||||||
},
|
},
|
||||||
fs: {
|
fs: {
|
||||||
strict: false,
|
|
||||||
allow: [
|
allow: [
|
||||||
nuxt.options.buildDir,
|
nuxt.options.appDir
|
||||||
nuxt.options.appDir,
|
|
||||||
nuxt.options.srcDir,
|
|
||||||
nuxt.options.rootDir,
|
|
||||||
...nuxt.options.modulesDir
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} as ViteOptions,
|
},
|
||||||
nuxt.options.vite as any || {}
|
nuxt.options.vite
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,18 +9,14 @@ export default defineBuildConfig({
|
|||||||
'@nuxt/kit',
|
'@nuxt/kit',
|
||||||
'unplugin',
|
'unplugin',
|
||||||
'webpack-virtual-modules',
|
'webpack-virtual-modules',
|
||||||
'@vue/babel-preset-jsx',
|
|
||||||
'postcss',
|
'postcss',
|
||||||
'postcss-import-resolver',
|
|
||||||
'postcss-loader',
|
'postcss-loader',
|
||||||
'babel-loader',
|
|
||||||
'vue-loader',
|
'vue-loader',
|
||||||
'css-loader',
|
'css-loader',
|
||||||
'file-loader',
|
'file-loader',
|
||||||
'style-resources-loader',
|
'style-resources-loader',
|
||||||
'url-loader',
|
'url-loader',
|
||||||
'vue-style-loader',
|
'vue-style-loader',
|
||||||
'@babel/core',
|
|
||||||
'vue'
|
'vue'
|
||||||
],
|
],
|
||||||
externals: [
|
externals: [
|
||||||
|
@ -19,9 +19,7 @@
|
|||||||
"@babel/core": "^7.17.5",
|
"@babel/core": "^7.17.5",
|
||||||
"@nuxt/friendly-errors-webpack-plugin": "^2.5.2",
|
"@nuxt/friendly-errors-webpack-plugin": "^2.5.2",
|
||||||
"@nuxt/kit": "3.0.0",
|
"@nuxt/kit": "3.0.0",
|
||||||
"@vue/babel-preset-jsx": "^1.2.4",
|
|
||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.2",
|
||||||
"babel-loader": "^8.2.3",
|
|
||||||
"css-loader": "^6.6.0",
|
"css-loader": "^6.6.0",
|
||||||
"css-minimizer-webpack-plugin": "^3.4.1",
|
"css-minimizer-webpack-plugin": "^3.4.1",
|
||||||
"cssnano": "^5.0.17",
|
"cssnano": "^5.0.17",
|
||||||
@ -29,7 +27,6 @@
|
|||||||
"escape-string-regexp": "^5.0.0",
|
"escape-string-regexp": "^5.0.0",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"fs-extra": "^10.0.1",
|
"fs-extra": "^10.0.1",
|
||||||
"glob": "^7.2.0",
|
|
||||||
"hash-sum": "^2.0.0",
|
"hash-sum": "^2.0.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"memfs": "^3.4.1",
|
"memfs": "^3.4.1",
|
||||||
@ -39,7 +36,6 @@
|
|||||||
"pify": "^5.0.0",
|
"pify": "^5.0.0",
|
||||||
"postcss": "^8.4.7",
|
"postcss": "^8.4.7",
|
||||||
"postcss-import": "^14.0.2",
|
"postcss-import": "^14.0.2",
|
||||||
"postcss-import-resolver": "^2.0.0",
|
|
||||||
"postcss-loader": "^6.2.1",
|
"postcss-loader": "^6.2.1",
|
||||||
"postcss-url": "^10.1.3",
|
"postcss-url": "^10.1.3",
|
||||||
"style-resources-loader": "^1.5.0",
|
"style-resources-loader": "^1.5.0",
|
||||||
@ -59,7 +55,6 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxt/schema": "3.0.0",
|
"@nuxt/schema": "3.0.0",
|
||||||
"@types/pify": "^5.0.1",
|
"@types/pify": "^5.0.1",
|
||||||
"@types/terser-webpack-plugin": "^5.0.4",
|
|
||||||
"@types/webpack-bundle-analyzer": "^4.4.1",
|
"@types/webpack-bundle-analyzer": "^4.4.1",
|
||||||
"@types/webpack-dev-middleware": "^5.0.2",
|
"@types/webpack-dev-middleware": "^5.0.2",
|
||||||
"@types/webpack-hot-middleware": "^2.25.6",
|
"@types/webpack-hot-middleware": "^2.25.6",
|
||||||
|
@ -3,7 +3,6 @@ import { resolve } from 'pathe'
|
|||||||
import webpack from 'webpack'
|
import webpack from 'webpack'
|
||||||
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
|
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
|
||||||
|
|
||||||
import type { ClientOptions } from 'webpack-hot-middleware'
|
|
||||||
import { joinURL } from 'ufo'
|
import { joinURL } from 'ufo'
|
||||||
import { applyPresets, WebpackConfigContext } from '../utils/config'
|
import { applyPresets, WebpackConfigContext } from '../utils/config'
|
||||||
import { nuxt } from '../presets/nuxt'
|
import { nuxt } from '../presets/nuxt'
|
||||||
@ -50,7 +49,7 @@ function clientHMR (ctx: WebpackConfigContext) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const clientOptions = options.build.hotMiddleware?.client || {} as ClientOptions
|
const clientOptions = options.webpack.hotMiddleware?.client || {}
|
||||||
const hotMiddlewareClientOptions = {
|
const hotMiddlewareClientOptions = {
|
||||||
reload: true,
|
reload: true,
|
||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
@ -81,7 +80,7 @@ function clientPlugins (ctx: WebpackConfigContext) {
|
|||||||
|
|
||||||
// Webpack Bundle Analyzer
|
// Webpack Bundle Analyzer
|
||||||
// https://github.com/webpack-contrib/webpack-bundle-analyzer
|
// https://github.com/webpack-contrib/webpack-bundle-analyzer
|
||||||
if (!ctx.isDev && ctx.name === 'client' && options.build.analyze) {
|
if (!ctx.isDev && ctx.name === 'client' && options.webpack.analyze) {
|
||||||
const statsDir = resolve(options.buildDir, 'stats')
|
const statsDir = resolve(options.buildDir, 'stats')
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@ -92,7 +91,7 @@ function clientPlugins (ctx: WebpackConfigContext) {
|
|||||||
openAnalyzer: !options.build.quiet,
|
openAnalyzer: !options.build.quiet,
|
||||||
reportFilename: resolve(statsDir, `${ctx.name}.html`),
|
reportFilename: resolve(statsDir, `${ctx.name}.html`),
|
||||||
statsFilename: resolve(statsDir, `${ctx.name}.json`),
|
statsFilename: resolve(statsDir, `${ctx.name}.json`),
|
||||||
...options.build.analyze as any
|
...options.webpack.analyze === true ? {} : options.webpack.analyze
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,10 +71,10 @@ function serverPlugins (ctx: WebpackConfigContext) {
|
|||||||
const { config, options } = ctx
|
const { config, options } = ctx
|
||||||
|
|
||||||
// Server polyfills
|
// Server polyfills
|
||||||
if (options.build.serverURLPolyfill) {
|
if (options.webpack.serverURLPolyfill) {
|
||||||
config.plugins.push(new webpack.ProvidePlugin({
|
config.plugins.push(new webpack.ProvidePlugin({
|
||||||
URL: [options.build.serverURLPolyfill, 'URL'],
|
URL: [options.webpack.serverURLPolyfill, 'URL'],
|
||||||
URLSearchParams: [options.build.serverURLPolyfill, 'URLSearchParams']
|
URLSearchParams: [options.webpack.serverURLPolyfill, 'URLSearchParams']
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
import type { WebpackError } from 'webpack'
|
import type { Compiler, WebpackError } from 'webpack'
|
||||||
export default class WarningIgnorePlugin {
|
|
||||||
filter: (warn: WebpackError) => boolean
|
|
||||||
|
|
||||||
constructor (filter) {
|
export type WarningFilter = (warn: WebpackError) => boolean
|
||||||
|
|
||||||
|
export default class WarningIgnorePlugin {
|
||||||
|
filter: WarningFilter
|
||||||
|
|
||||||
|
constructor (filter: WarningFilter) {
|
||||||
this.filter = filter
|
this.filter = filter
|
||||||
}
|
}
|
||||||
|
|
||||||
apply (compiler) /* istanbul ignore next */ {
|
apply (compiler: Compiler) {
|
||||||
compiler.hooks.done.tap('warnfix-plugin', (stats) => {
|
compiler.hooks.done.tap('warnfix-plugin', (stats) => {
|
||||||
stats.compilation.warnings = stats.compilation.warnings.filter(this.filter)
|
stats.compilation.warnings = stats.compilation.warnings.filter(this.filter)
|
||||||
})
|
})
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
import { fileName, WebpackConfigContext } from '../utils/config'
|
import { fileName, WebpackConfigContext } from '../utils/config'
|
||||||
|
|
||||||
export function assets (ctx: WebpackConfigContext) {
|
export function assets (ctx: WebpackConfigContext) {
|
||||||
const { options } = ctx
|
|
||||||
|
|
||||||
ctx.config.module.rules.push(
|
ctx.config.module.rules.push(
|
||||||
{
|
{
|
||||||
test: /\.(png|jpe?g|gif|svg|webp)$/i,
|
test: /\.(png|jpe?g|gif|svg|webp)$/i,
|
||||||
use: [{
|
use: [{
|
||||||
loader: 'url-loader',
|
loader: 'url-loader',
|
||||||
options: {
|
options: {
|
||||||
...options.build.loaders.imgUrl,
|
...ctx.options.webpack.loaders.imgUrl,
|
||||||
name: fileName(ctx, 'img')
|
name: fileName(ctx, 'img')
|
||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
@ -19,7 +17,7 @@ export function assets (ctx: WebpackConfigContext) {
|
|||||||
use: [{
|
use: [{
|
||||||
loader: 'url-loader',
|
loader: 'url-loader',
|
||||||
options: {
|
options: {
|
||||||
...options.build.loaders.fontUrl,
|
...ctx.options.webpack.loaders.fontUrl,
|
||||||
name: fileName(ctx, 'font')
|
name: fileName(ctx, 'font')
|
||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
@ -29,7 +27,7 @@ export function assets (ctx: WebpackConfigContext) {
|
|||||||
use: [{
|
use: [{
|
||||||
loader: 'file-loader',
|
loader: 'file-loader',
|
||||||
options: {
|
options: {
|
||||||
...options.build.loaders.file,
|
...ctx.options.webpack.loaders.file,
|
||||||
name: fileName(ctx, 'video')
|
name: fileName(ctx, 'video')
|
||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
|
@ -1,84 +0,0 @@
|
|||||||
import { createRequire } from 'module'
|
|
||||||
import { normalize } from 'pathe'
|
|
||||||
import TerserWebpackPlugin from 'terser-webpack-plugin'
|
|
||||||
import { reservedVueTags } from '../utils/reserved-tags'
|
|
||||||
import { WebpackConfigContext } from '../utils/config'
|
|
||||||
|
|
||||||
const _require = createRequire(import.meta.url)
|
|
||||||
|
|
||||||
export function babel (ctx: WebpackConfigContext) {
|
|
||||||
const { config, options } = ctx
|
|
||||||
|
|
||||||
const babelLoader = {
|
|
||||||
loader: normalize(_require.resolve('babel-loader')),
|
|
||||||
options: getBabelOptions(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
config.module.rules.push({
|
|
||||||
test: /\.m?[jt]sx?$/i,
|
|
||||||
exclude: (file) => {
|
|
||||||
file = file.split('node_modules', 2)[1]
|
|
||||||
// not exclude files outside node_modules
|
|
||||||
if (!file) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// item in transpile can be string or regex object
|
|
||||||
return !ctx.transpile.some(module => module.test(file))
|
|
||||||
},
|
|
||||||
resolve: {
|
|
||||||
fullySpecified: false
|
|
||||||
},
|
|
||||||
use: babelLoader
|
|
||||||
})
|
|
||||||
|
|
||||||
// https://github.com/webpack-contrib/terser-webpack-plugin
|
|
||||||
if (options.build.terser) {
|
|
||||||
const terser = new TerserWebpackPlugin({
|
|
||||||
// cache, TODO
|
|
||||||
extractComments: {
|
|
||||||
condition: 'some',
|
|
||||||
filename: 'LICENSES'
|
|
||||||
},
|
|
||||||
terserOptions: {
|
|
||||||
compress: {
|
|
||||||
ecma: ctx.isModern ? 6 : undefined
|
|
||||||
},
|
|
||||||
mangle: {
|
|
||||||
reserved: reservedVueTags
|
|
||||||
}
|
|
||||||
},
|
|
||||||
...options.build.terser as any
|
|
||||||
})
|
|
||||||
|
|
||||||
config.plugins.push(terser as any)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBabelOptions (ctx: WebpackConfigContext) {
|
|
||||||
const { options } = ctx
|
|
||||||
|
|
||||||
const babelOptions: any = {
|
|
||||||
...options.build.babel,
|
|
||||||
envName: ctx.name
|
|
||||||
}
|
|
||||||
|
|
||||||
if (babelOptions.configFile || babelOptions.babelrc) {
|
|
||||||
return babelOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof babelOptions.plugins === 'function') {
|
|
||||||
babelOptions.plugins = babelOptions.plugins(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultPreset = [normalize(_require.resolve('../../babel-preset-app')), {}]
|
|
||||||
|
|
||||||
if (typeof babelOptions.presets === 'function') {
|
|
||||||
babelOptions.presets = babelOptions.presets(ctx, defaultPreset)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!babelOptions.presets) {
|
|
||||||
babelOptions.presets = [defaultPreset]
|
|
||||||
}
|
|
||||||
|
|
||||||
return babelOptions
|
|
||||||
}
|
|
@ -6,7 +6,7 @@ import { logger } from '@nuxt/kit'
|
|||||||
import FriendlyErrorsWebpackPlugin from '@nuxt/friendly-errors-webpack-plugin'
|
import FriendlyErrorsWebpackPlugin from '@nuxt/friendly-errors-webpack-plugin'
|
||||||
import escapeRegExp from 'escape-string-regexp'
|
import escapeRegExp from 'escape-string-regexp'
|
||||||
import { joinURL } from 'ufo'
|
import { joinURL } from 'ufo'
|
||||||
import WarningIgnorePlugin from '../plugins/warning-ignore'
|
import WarningIgnorePlugin, { WarningFilter } from '../plugins/warning-ignore'
|
||||||
import { WebpackConfigContext, applyPresets, fileName } from '../utils/config'
|
import { WebpackConfigContext, applyPresets, fileName } from '../utils/config'
|
||||||
|
|
||||||
export function base (ctx: WebpackConfigContext) {
|
export function base (ctx: WebpackConfigContext) {
|
||||||
@ -28,7 +28,7 @@ function baseConfig (ctx: WebpackConfigContext) {
|
|||||||
plugins: [],
|
plugins: [],
|
||||||
externals: [],
|
externals: [],
|
||||||
optimization: {
|
optimization: {
|
||||||
...options.build.optimization as any,
|
...options.webpack.optimization,
|
||||||
minimizer: []
|
minimizer: []
|
||||||
},
|
},
|
||||||
experiments: {},
|
experiments: {},
|
||||||
@ -43,13 +43,13 @@ function baseConfig (ctx: WebpackConfigContext) {
|
|||||||
function basePlugins (ctx: WebpackConfigContext) {
|
function basePlugins (ctx: WebpackConfigContext) {
|
||||||
const { config, options, nuxt } = ctx
|
const { config, options, nuxt } = ctx
|
||||||
|
|
||||||
// Add timefix-plugin before others plugins
|
// Add timefix-plugin before other plugins
|
||||||
if (options.dev) {
|
if (options.dev) {
|
||||||
config.plugins.push(new TimeFixPlugin())
|
config.plugins.push(new TimeFixPlugin())
|
||||||
}
|
}
|
||||||
|
|
||||||
// User plugins
|
// User plugins
|
||||||
config.plugins.push(...(options.build.plugins || []))
|
config.plugins.push(...(options.webpack.plugins || []))
|
||||||
|
|
||||||
// Ignore empty warnings
|
// Ignore empty warnings
|
||||||
config.plugins.push(new WarningIgnorePlugin(getWarningIgnoreFilter(ctx)))
|
config.plugins.push(new WarningIgnorePlugin(getWarningIgnoreFilter(ctx)))
|
||||||
@ -60,7 +60,7 @@ function basePlugins (ctx: WebpackConfigContext) {
|
|||||||
// Friendly errors
|
// Friendly errors
|
||||||
if (
|
if (
|
||||||
ctx.isServer ||
|
ctx.isServer ||
|
||||||
(ctx.isDev && !options.build.quiet && options.build.friendlyErrors)
|
(ctx.isDev && !options.build.quiet && options.webpack.friendlyErrors)
|
||||||
) {
|
) {
|
||||||
ctx.config.plugins.push(
|
ctx.config.plugins.push(
|
||||||
new FriendlyErrorsWebpackPlugin({
|
new FriendlyErrorsWebpackPlugin({
|
||||||
@ -71,39 +71,41 @@ function basePlugins (ctx: WebpackConfigContext) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Webpackbar
|
if (nuxt.options.webpack.profile) {
|
||||||
const colors = {
|
// Webpackbar
|
||||||
client: 'green',
|
const colors = {
|
||||||
server: 'orange',
|
client: 'green',
|
||||||
modern: 'blue'
|
server: 'orange',
|
||||||
}
|
modern: 'blue'
|
||||||
config.plugins.push(new WebpackBar({
|
|
||||||
name: ctx.name,
|
|
||||||
color: colors[ctx.name],
|
|
||||||
reporters: ['stats'],
|
|
||||||
stats: !ctx.isDev,
|
|
||||||
reporter: {
|
|
||||||
// @ts-ignore
|
|
||||||
change: (_, { shortPath }) => {
|
|
||||||
if (!ctx.isServer) {
|
|
||||||
nuxt.callHook('bundler:change', shortPath)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
done: ({ state }) => {
|
|
||||||
if (state.hasErrors) {
|
|
||||||
nuxt.callHook('bundler:error')
|
|
||||||
} else {
|
|
||||||
logger.success(`${state.name} ${state.message}`)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
allDone: () => {
|
|
||||||
nuxt.callHook('bundler:done')
|
|
||||||
},
|
|
||||||
progress ({ statesArray }) {
|
|
||||||
nuxt.callHook('bundler:progress', statesArray)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}))
|
config.plugins.push(new WebpackBar({
|
||||||
|
name: ctx.name,
|
||||||
|
color: colors[ctx.name],
|
||||||
|
reporters: ['stats'],
|
||||||
|
stats: !ctx.isDev,
|
||||||
|
reporter: {
|
||||||
|
// @ts-ignore
|
||||||
|
change: (_, { shortPath }) => {
|
||||||
|
if (!ctx.isServer) {
|
||||||
|
nuxt.callHook('bundler:change', shortPath)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
done: ({ state }) => {
|
||||||
|
if (state.hasErrors) {
|
||||||
|
nuxt.callHook('bundler:error')
|
||||||
|
} else {
|
||||||
|
logger.success(`${state.name} ${state.message}`)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
allDone: () => {
|
||||||
|
nuxt.callHook('bundler:done')
|
||||||
|
},
|
||||||
|
progress ({ statesArray }) {
|
||||||
|
nuxt.callHook('bundler:progress', statesArray)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function baseAlias (ctx: WebpackConfigContext) {
|
function baseAlias (ctx: WebpackConfigContext) {
|
||||||
@ -198,15 +200,15 @@ function getOutput (ctx: WebpackConfigContext): webpack.Configuration['output']
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWarningIgnoreFilter (ctx: WebpackConfigContext) {
|
function getWarningIgnoreFilter (ctx: WebpackConfigContext): WarningFilter {
|
||||||
const { options } = ctx
|
const { options } = ctx
|
||||||
|
|
||||||
const filters = [
|
const filters: WarningFilter[] = [
|
||||||
// Hide warnings about plugins without a default export (#1179)
|
// Hide warnings about plugins without a default export (#1179)
|
||||||
warn => warn.name === 'ModuleDependencyWarning' &&
|
warn => warn.name === 'ModuleDependencyWarning' &&
|
||||||
warn.message.includes('export \'default\'') &&
|
warn.message.includes('export \'default\'') &&
|
||||||
warn.message.includes('nuxt_plugin_'),
|
warn.message.includes('nuxt_plugin_'),
|
||||||
...(options.build.warningIgnoreFilters || [])
|
...(options.webpack.warningIgnoreFilters || [])
|
||||||
]
|
]
|
||||||
|
|
||||||
return warn => !filters.some(ignoreFilter => ignoreFilter(warn))
|
return warn => !filters.some(ignoreFilter => ignoreFilter(warn))
|
||||||
@ -224,11 +226,10 @@ function getEnv (ctx: WebpackConfigContext) {
|
|||||||
'process.env.VUE_ENV': JSON.stringify(ctx.name),
|
'process.env.VUE_ENV': JSON.stringify(ctx.name),
|
||||||
'process.browser': ctx.isClient,
|
'process.browser': ctx.isClient,
|
||||||
'process.client': ctx.isClient,
|
'process.client': ctx.isClient,
|
||||||
'process.server': ctx.isServer,
|
'process.server': ctx.isServer
|
||||||
'process.modern': ctx.isModern
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.build.aggressiveCodeRemoval) {
|
if (options.webpack.aggressiveCodeRemoval) {
|
||||||
_env['typeof process'] = JSON.stringify(ctx.isServer ? 'object' : 'undefined')
|
_env['typeof process'] = JSON.stringify(ctx.isServer ? 'object' : 'undefined')
|
||||||
_env['typeof window'] = _env['typeof document'] = JSON.stringify(!ctx.isServer ? 'object' : 'undefined')
|
_env['typeof window'] = _env['typeof document'] = JSON.stringify(!ctx.isServer ? 'object' : 'undefined')
|
||||||
}
|
}
|
||||||
|
@ -17,14 +17,10 @@ export function esbuild (ctx: WebpackConfigContext) {
|
|||||||
test: /\.m?[jt]s$/i,
|
test: /\.m?[jt]s$/i,
|
||||||
loader: 'esbuild-loader',
|
loader: 'esbuild-loader',
|
||||||
exclude: (file) => {
|
exclude: (file) => {
|
||||||
file = file.split('node_modules', 2)[1]
|
|
||||||
|
|
||||||
// Not exclude files outside node_modules
|
// Not exclude files outside node_modules
|
||||||
if (!file) {
|
file = file.split('node_modules', 2)[1]
|
||||||
return false
|
if (!file) { return false }
|
||||||
}
|
|
||||||
|
|
||||||
// Item in transpile can be string or regex object
|
|
||||||
return !ctx.transpile.some(module => module.test(file))
|
return !ctx.transpile.some(module => module.test(file))
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { WebpackConfigContext } from '../utils/config'
|
import type { WebpackConfigContext } from '../utils/config'
|
||||||
|
|
||||||
export function node (ctx: WebpackConfigContext) {
|
export function node (ctx: WebpackConfigContext) {
|
||||||
const { config } = ctx
|
const { config } = ctx
|
||||||
|
@ -11,7 +11,6 @@ export function nuxt (ctx: WebpackConfigContext) {
|
|||||||
applyPresets(ctx, [
|
applyPresets(ctx, [
|
||||||
base,
|
base,
|
||||||
assets,
|
assets,
|
||||||
// babel,
|
|
||||||
esbuild,
|
esbuild,
|
||||||
pug,
|
pug,
|
||||||
style,
|
style,
|
||||||
|
@ -8,7 +8,7 @@ export function pug (ctx: WebpackConfigContext) {
|
|||||||
resourceQuery: /^\?vue/i,
|
resourceQuery: /^\?vue/i,
|
||||||
use: [{
|
use: [{
|
||||||
loader: 'pug-plain-loader',
|
loader: 'pug-plain-loader',
|
||||||
options: ctx.options.build.loaders.pugPlain
|
options: ctx.options.webpack.loaders.pugPlain
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -16,7 +16,7 @@ export function pug (ctx: WebpackConfigContext) {
|
|||||||
'raw-loader',
|
'raw-loader',
|
||||||
{
|
{
|
||||||
loader: 'pug-plain-loader',
|
loader: 'pug-plain-loader',
|
||||||
options: ctx.options.build.loaders.pugPlain
|
options: ctx.options.webpack.loaders.pugPlain
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { resolve } from 'pathe'
|
|
||||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
|
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
|
||||||
import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'
|
import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'
|
||||||
import { fileName, WebpackConfigContext, applyPresets } from '../utils/config'
|
import { fileName, WebpackConfigContext, applyPresets } from '../utils/config'
|
||||||
import { PostcssConfig } from '../utils/postcss'
|
import { getPostcssConfig } from '../utils/postcss'
|
||||||
|
|
||||||
export function style (ctx: WebpackConfigContext) {
|
export function style (ctx: WebpackConfigContext) {
|
||||||
applyPresets(ctx, [
|
applyPresets(ctx, [
|
||||||
@ -15,9 +14,9 @@ export function style (ctx: WebpackConfigContext) {
|
|||||||
function minimizer (ctx: WebpackConfigContext) {
|
function minimizer (ctx: WebpackConfigContext) {
|
||||||
const { options, config } = ctx
|
const { options, config } = ctx
|
||||||
|
|
||||||
if (options.build.optimizeCSS && Array.isArray(config.optimization.minimizer)) {
|
if (options.webpack.optimizeCSS && Array.isArray(config.optimization.minimizer)) {
|
||||||
config.optimization.minimizer.push(new CssMinimizerPlugin({
|
config.optimization.minimizer.push(new CssMinimizerPlugin({
|
||||||
...options.build.optimizeCSS as any
|
...options.webpack.optimizeCSS
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -26,11 +25,11 @@ function extractCSS (ctx: WebpackConfigContext) {
|
|||||||
const { options, config } = ctx
|
const { options, config } = ctx
|
||||||
|
|
||||||
// CSS extraction
|
// CSS extraction
|
||||||
if (options.build.extractCSS) {
|
if (options.webpack.extractCSS) {
|
||||||
config.plugins.push(new MiniCssExtractPlugin({
|
config.plugins.push(new MiniCssExtractPlugin({
|
||||||
filename: fileName(ctx, 'css'),
|
filename: fileName(ctx, 'css'),
|
||||||
chunkFilename: fileName(ctx, 'css'),
|
chunkFilename: fileName(ctx, 'css'),
|
||||||
...(options.build.extractCSS as any)
|
...options.webpack.extractCSS
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,18 +44,18 @@ function loaders (ctx: WebpackConfigContext) {
|
|||||||
config.module.rules.push(createdStyleRule('postcss', /\.p(ost)?css$/i, null, ctx))
|
config.module.rules.push(createdStyleRule('postcss', /\.p(ost)?css$/i, null, ctx))
|
||||||
|
|
||||||
// Less
|
// Less
|
||||||
const lessLoader = { loader: 'less-loader', options: options.build.loaders.less }
|
const lessLoader = { loader: 'less-loader', options: options.webpack.loaders.less }
|
||||||
config.module.rules.push(createdStyleRule('less', /\.less$/i, lessLoader, ctx))
|
config.module.rules.push(createdStyleRule('less', /\.less$/i, lessLoader, ctx))
|
||||||
|
|
||||||
// Sass (TODO: optional dependency)
|
// Sass (TODO: optional dependency)
|
||||||
const sassLoader = { loader: 'sass-loader', options: options.build.loaders.sass }
|
const sassLoader = { loader: 'sass-loader', options: options.webpack.loaders.sass }
|
||||||
config.module.rules.push(createdStyleRule('sass', /\.sass$/i, sassLoader, ctx))
|
config.module.rules.push(createdStyleRule('sass', /\.sass$/i, sassLoader, ctx))
|
||||||
|
|
||||||
const scssLoader = { loader: 'sass-loader', options: options.build.loaders.scss }
|
const scssLoader = { loader: 'sass-loader', options: options.webpack.loaders.scss }
|
||||||
config.module.rules.push(createdStyleRule('scss', /\.scss$/i, scssLoader, ctx))
|
config.module.rules.push(createdStyleRule('scss', /\.scss$/i, scssLoader, ctx))
|
||||||
|
|
||||||
// Stylus
|
// Stylus
|
||||||
const stylusLoader = { loader: 'stylus-loader', options: options.build.loaders.stylus }
|
const stylusLoader = { loader: 'stylus-loader', options: options.webpack.loaders.stylus }
|
||||||
config.module.rules.push(createdStyleRule('stylus', /\.styl(us)?$/i, stylusLoader, ctx))
|
config.module.rules.push(createdStyleRule('stylus', /\.styl(us)?$/i, stylusLoader, ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,16 +64,15 @@ function createdStyleRule (lang: string, test: RegExp, processorLoader, ctx: Web
|
|||||||
|
|
||||||
const styleLoaders = [
|
const styleLoaders = [
|
||||||
createPostcssLoadersRule(ctx),
|
createPostcssLoadersRule(ctx),
|
||||||
processorLoader,
|
processorLoader
|
||||||
createStyleResourcesLoaderRule(lang, options.build.styleResources, options.rootDir)
|
|
||||||
].filter(Boolean)
|
].filter(Boolean)
|
||||||
|
|
||||||
options.build.loaders.css.importLoaders =
|
options.webpack.loaders.css.importLoaders =
|
||||||
options.build.loaders.cssModules.importLoaders =
|
options.webpack.loaders.cssModules.importLoaders =
|
||||||
styleLoaders.length
|
styleLoaders.length
|
||||||
|
|
||||||
const cssLoaders = createCssLoadersRule(ctx, options.build.loaders.css)
|
const cssLoaders = createCssLoadersRule(ctx, options.webpack.loaders.css)
|
||||||
const cssModuleLoaders = createCssLoadersRule(ctx, options.build.loaders.cssModules)
|
const cssModuleLoaders = createCssLoadersRule(ctx, options.webpack.loaders.cssModules)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
test,
|
test,
|
||||||
@ -97,7 +95,7 @@ function createCssLoadersRule (ctx: WebpackConfigContext, cssLoaderOptions) {
|
|||||||
|
|
||||||
const cssLoader = { loader: 'css-loader', options: cssLoaderOptions }
|
const cssLoader = { loader: 'css-loader', options: cssLoaderOptions }
|
||||||
|
|
||||||
if (options.build.extractCSS) {
|
if (options.webpack.extractCSS) {
|
||||||
if (ctx.isServer) {
|
if (ctx.isServer) {
|
||||||
return [cssLoader]
|
return [cssLoader]
|
||||||
}
|
}
|
||||||
@ -113,37 +111,18 @@ function createCssLoadersRule (ctx: WebpackConfigContext, cssLoaderOptions) {
|
|||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
loader: 'vue-style-loader',
|
loader: 'vue-style-loader',
|
||||||
options: options.build.loaders.vueStyle
|
options: options.webpack.loaders.vueStyle
|
||||||
},
|
},
|
||||||
cssLoader
|
cssLoader
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
function createStyleResourcesLoaderRule (styleLang, styleResources, rootDir) {
|
|
||||||
// style-resources-loader
|
|
||||||
// https://github.com/yenshih/style-resources-loader
|
|
||||||
if (!styleResources[styleLang]) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
loader: 'style-resources-loader',
|
|
||||||
options: {
|
|
||||||
patterns: Array.from(styleResources[styleLang]).map(p => resolve(rootDir, p as string)),
|
|
||||||
...styleResources.options
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function createPostcssLoadersRule (ctx: WebpackConfigContext) {
|
function createPostcssLoadersRule (ctx: WebpackConfigContext) {
|
||||||
const { options, nuxt } = ctx
|
const { options, nuxt } = ctx
|
||||||
|
|
||||||
if (!options.build.postcss) {
|
if (!options.postcss) { return }
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const postcssConfig = new PostcssConfig(nuxt)
|
const config = getPostcssConfig(nuxt)
|
||||||
const config = postcssConfig.config()
|
|
||||||
|
|
||||||
if (!config) {
|
if (!config) {
|
||||||
return
|
return
|
||||||
|
@ -14,7 +14,7 @@ export function vue (ctx: WebpackConfigContext) {
|
|||||||
config.module.rules.push({
|
config.module.rules.push({
|
||||||
test: /\.vue$/i,
|
test: /\.vue$/i,
|
||||||
loader: 'vue-loader',
|
loader: 'vue-loader',
|
||||||
options: options.build.loaders.vue
|
options: options.webpack.loaders.vue
|
||||||
})
|
})
|
||||||
|
|
||||||
if (ctx.isClient) {
|
if (ctx.isClient) {
|
||||||
|
@ -1,202 +0,0 @@
|
|||||||
const coreJsMeta = {
|
|
||||||
2: {
|
|
||||||
prefixes: {
|
|
||||||
es6: 'es6',
|
|
||||||
es7: 'es7'
|
|
||||||
},
|
|
||||||
builtIns: '@babel/compat-data/corejs2-built-ins'
|
|
||||||
},
|
|
||||||
3: {
|
|
||||||
prefixes: {
|
|
||||||
es6: 'es',
|
|
||||||
es7: 'es'
|
|
||||||
},
|
|
||||||
builtIns: 'core-js-compat/data'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDefaultPolyfills (corejs) {
|
|
||||||
const { prefixes: { es6, es7 } } = coreJsMeta[corejs.version]
|
|
||||||
return [
|
|
||||||
// Promise polyfill alone doesn't work in IE,
|
|
||||||
// Needs this as well. see: #1642
|
|
||||||
`${es6}.array.iterator`,
|
|
||||||
// This is required for webpack code splitting, vuex etc.
|
|
||||||
`${es6}.promise`,
|
|
||||||
// this is needed for object rest spread support in templates
|
|
||||||
// as vue-template-es2015-compiler 1.8+ compiles it to Object.assign() calls.
|
|
||||||
`${es6}.object.assign`,
|
|
||||||
// #2012 es7.promise replaces native Promise in FF and causes missing finally
|
|
||||||
`${es7}.promise.finally`
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPolyfills (targets, includes, { ignoreBrowserslistConfig, configPath, corejs }) {
|
|
||||||
const { default: getTargets, isRequired } = require('@babel/helper-compilation-targets')
|
|
||||||
const builtInsList = require(coreJsMeta[corejs.version].builtIns)
|
|
||||||
const builtInTargets = getTargets(targets, {
|
|
||||||
ignoreBrowserslistConfig,
|
|
||||||
configPath
|
|
||||||
})
|
|
||||||
|
|
||||||
return includes.filter(item => isRequired(
|
|
||||||
'nuxt-polyfills',
|
|
||||||
builtInTargets,
|
|
||||||
{
|
|
||||||
compatData: { 'nuxt-polyfills': builtInsList[item] }
|
|
||||||
}
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
function isPackageHoisted (packageName) {
|
|
||||||
const path = require('pathe')
|
|
||||||
const installedPath = path.normalize(require.resolve(packageName))
|
|
||||||
const relativePath = path.resolve(__dirname, '..', 'node_modules', packageName)
|
|
||||||
return installedPath !== relativePath
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = (api, options = {}) => {
|
|
||||||
const presets = []
|
|
||||||
const plugins = []
|
|
||||||
|
|
||||||
const envName = api.env()
|
|
||||||
|
|
||||||
const {
|
|
||||||
bugfixes,
|
|
||||||
polyfills: userPolyfills,
|
|
||||||
loose = false,
|
|
||||||
debug = false,
|
|
||||||
useBuiltIns = 'usage',
|
|
||||||
modules = false,
|
|
||||||
spec,
|
|
||||||
ignoreBrowserslistConfig = envName === 'modern',
|
|
||||||
configPath,
|
|
||||||
include,
|
|
||||||
exclude,
|
|
||||||
shippedProposals,
|
|
||||||
forceAllTransforms,
|
|
||||||
decoratorsBeforeExport,
|
|
||||||
decoratorsLegacy,
|
|
||||||
absoluteRuntime
|
|
||||||
} = options
|
|
||||||
|
|
||||||
let { corejs = { version: 3 } } = options
|
|
||||||
|
|
||||||
if (typeof corejs !== 'object') {
|
|
||||||
corejs = { version: Number(corejs) }
|
|
||||||
}
|
|
||||||
|
|
||||||
const isCorejs3Hoisted = isPackageHoisted('core-js')
|
|
||||||
if (
|
|
||||||
(corejs.version === 3 && !isCorejs3Hoisted) ||
|
|
||||||
(corejs.version === 2 && isCorejs3Hoisted)
|
|
||||||
) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
(console.fatal || console.error)(`babel corejs option is ${corejs.version}, please directly install core-js@${corejs.version}.`)
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultTargets = {
|
|
||||||
server: { node: 'current' },
|
|
||||||
client: { ie: 9 },
|
|
||||||
modern: { esmodules: true }
|
|
||||||
}
|
|
||||||
|
|
||||||
let { targets = defaultTargets[envName] } = options
|
|
||||||
|
|
||||||
// modern mode can only be { esmodules: true }
|
|
||||||
if (envName === 'modern') {
|
|
||||||
targets = defaultTargets.modern
|
|
||||||
}
|
|
||||||
|
|
||||||
const polyfills = []
|
|
||||||
|
|
||||||
if (envName === 'client' && useBuiltIns === 'usage') {
|
|
||||||
polyfills.push(
|
|
||||||
...getPolyfills(
|
|
||||||
targets,
|
|
||||||
userPolyfills || getDefaultPolyfills(corejs),
|
|
||||||
{
|
|
||||||
ignoreBrowserslistConfig,
|
|
||||||
configPath,
|
|
||||||
corejs
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
plugins.push([polyfillsPlugin, { polyfills }])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass options along to babel-preset-env
|
|
||||||
presets.push([
|
|
||||||
require('@babel/preset-env'), {
|
|
||||||
bugfixes,
|
|
||||||
spec,
|
|
||||||
loose,
|
|
||||||
debug,
|
|
||||||
modules,
|
|
||||||
targets,
|
|
||||||
useBuiltIns,
|
|
||||||
corejs,
|
|
||||||
ignoreBrowserslistConfig,
|
|
||||||
configPath,
|
|
||||||
include,
|
|
||||||
exclude: polyfills.concat(exclude || []),
|
|
||||||
shippedProposals,
|
|
||||||
forceAllTransforms
|
|
||||||
}
|
|
||||||
], [
|
|
||||||
require('@babel/preset-typescript')
|
|
||||||
])
|
|
||||||
|
|
||||||
// JSX
|
|
||||||
if (options.jsx !== false) {
|
|
||||||
// presets.push([require('@vue/babel-preset-jsx'), Object.assign({}, options.jsx)])
|
|
||||||
}
|
|
||||||
|
|
||||||
plugins.push(
|
|
||||||
[require('@babel/plugin-proposal-decorators'), {
|
|
||||||
decoratorsBeforeExport,
|
|
||||||
legacy: decoratorsLegacy !== false
|
|
||||||
}],
|
|
||||||
[require('@babel/plugin-proposal-class-properties'), { loose: true }]
|
|
||||||
)
|
|
||||||
|
|
||||||
// Transform runtime, but only for helpers
|
|
||||||
plugins.push([require('@babel/plugin-transform-runtime'), {
|
|
||||||
regenerator: useBuiltIns !== 'usage',
|
|
||||||
corejs: false,
|
|
||||||
helpers: useBuiltIns === 'usage',
|
|
||||||
useESModules: envName !== 'server',
|
|
||||||
absoluteRuntime
|
|
||||||
}])
|
|
||||||
|
|
||||||
return {
|
|
||||||
sourceType: 'unambiguous',
|
|
||||||
presets,
|
|
||||||
plugins
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add polyfill imports to the first file encountered.
|
|
||||||
function polyfillsPlugin ({ _types }) {
|
|
||||||
let entryFile
|
|
||||||
return {
|
|
||||||
name: 'inject-polyfills',
|
|
||||||
visitor: {
|
|
||||||
Program (path, state) {
|
|
||||||
if (!entryFile) {
|
|
||||||
entryFile = state.filename
|
|
||||||
} else if (state.filename !== entryFile) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const { polyfills } = state.opts
|
|
||||||
const { createImport } = require('@babel/preset-env/lib/utils')
|
|
||||||
|
|
||||||
// Imports are injected in reverse order
|
|
||||||
polyfills.slice().reverse().forEach((p) => {
|
|
||||||
createImport(path, p)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,21 +8,19 @@ export interface WebpackConfigContext extends ReturnType<typeof createWebpackCon
|
|||||||
type WebpackConfigPreset = (ctx: WebpackConfigContext, options?: object) => void
|
type WebpackConfigPreset = (ctx: WebpackConfigContext, options?: object) => void
|
||||||
type WebpackConfigPresetItem = WebpackConfigPreset | [WebpackConfigPreset, any]
|
type WebpackConfigPresetItem = WebpackConfigPreset | [WebpackConfigPreset, any]
|
||||||
|
|
||||||
export function createWebpackConfigContext ({ nuxt }) {
|
export function createWebpackConfigContext (nuxt: Nuxt) {
|
||||||
return {
|
return {
|
||||||
nuxt: nuxt as Nuxt,
|
nuxt,
|
||||||
options: nuxt.options as Nuxt['options'],
|
options: nuxt.options,
|
||||||
config: {} as Configuration,
|
config: {} as Configuration,
|
||||||
|
|
||||||
name: 'base',
|
name: 'base',
|
||||||
isDev: nuxt.options.dev,
|
isDev: nuxt.options.dev,
|
||||||
isServer: false,
|
isServer: false,
|
||||||
isClient: false,
|
isClient: false,
|
||||||
isModern: undefined, // TODO
|
|
||||||
isLegacy: false,
|
|
||||||
|
|
||||||
alias: {} as Configuration['resolve']['alias'],
|
alias: {} as Configuration['resolve']['alias'],
|
||||||
transpile: [] as any[]
|
transpile: [] as RegExp[]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +40,7 @@ export function applyPresets (ctx: WebpackConfigContext, presets: WebpackConfigP
|
|||||||
export function fileName (ctx: WebpackConfigContext, key: string) {
|
export function fileName (ctx: WebpackConfigContext, key: string) {
|
||||||
const { options } = ctx
|
const { options } = ctx
|
||||||
|
|
||||||
let fileName = options.build.filenames[key]
|
let fileName = options.webpack.filenames[key]
|
||||||
|
|
||||||
if (typeof fileName === 'function') {
|
if (typeof fileName === 'function') {
|
||||||
fileName = fileName(ctx)
|
fileName = fileName(ctx)
|
||||||
|
@ -9,7 +9,7 @@ export function createMFS () {
|
|||||||
const fs = createFsFromVolume(new Volume())
|
const fs = createFsFromVolume(new Volume())
|
||||||
|
|
||||||
// Clone to extend
|
// Clone to extend
|
||||||
const _fs : Partial<IFs> & { join?(...paths: string[]): string } = { ...fs }
|
const _fs: Partial<IFs> & { join?(...paths: string[]): string } = { ...fs }
|
||||||
|
|
||||||
// fs.join method is (still) expected by webpack-dev-middleware
|
// fs.join method is (still) expected by webpack-dev-middleware
|
||||||
// There might be differences with https://github.com/webpack/memory-fs/blob/master/lib/join.js
|
// There might be differences with https://github.com/webpack/memory-fs/blob/master/lib/join.js
|
||||||
@ -19,5 +19,5 @@ export function createMFS () {
|
|||||||
_fs.exists = p => Promise.resolve(_fs.existsSync(p))
|
_fs.exists = p => Promise.resolve(_fs.existsSync(p))
|
||||||
_fs.readFile = pify(_fs.readFile)
|
_fs.readFile = pify(_fs.readFile)
|
||||||
|
|
||||||
return _fs
|
return _fs as IFs & { join?(...paths: string[]): string }
|
||||||
}
|
}
|
||||||
|
@ -1,136 +1,41 @@
|
|||||||
import fs from 'fs'
|
|
||||||
import { resolve } from 'pathe'
|
|
||||||
import { logger, requireModule } from '@nuxt/kit'
|
|
||||||
import { createCommonJS } from 'mlly'
|
import { createCommonJS } from 'mlly'
|
||||||
import { defaults, merge, cloneDeep } from 'lodash-es'
|
import { defaults, merge, cloneDeep } from 'lodash-es'
|
||||||
import createResolver from 'postcss-import-resolver'
|
import { requireModule } from '@nuxt/kit'
|
||||||
import type { Nuxt } from '@nuxt/schema'
|
import type { Nuxt } from '@nuxt/schema'
|
||||||
|
|
||||||
const isPureObject = obj => obj !== null && !Array.isArray(obj) && typeof obj === 'object'
|
const isPureObject = (obj: unknown): obj is Object => obj !== null && !Array.isArray(obj) && typeof obj === 'object'
|
||||||
|
|
||||||
export const orderPresets = {
|
export const orderPresets = {
|
||||||
cssnanoLast (names) {
|
cssnanoLast (names: string[]) {
|
||||||
const nanoIndex = names.indexOf('cssnano')
|
const nanoIndex = names.indexOf('cssnano')
|
||||||
if (nanoIndex !== names.length - 1) {
|
if (nanoIndex !== names.length - 1) {
|
||||||
names.push(names.splice(nanoIndex, 1)[0])
|
names.push(names.splice(nanoIndex, 1)[0])
|
||||||
}
|
}
|
||||||
return names
|
return names
|
||||||
},
|
},
|
||||||
autoprefixerLast (names) {
|
autoprefixerLast (names: string[]) {
|
||||||
const nanoIndex = names.indexOf('autoprefixer')
|
const nanoIndex = names.indexOf('autoprefixer')
|
||||||
if (nanoIndex !== names.length - 1) {
|
if (nanoIndex !== names.length - 1) {
|
||||||
names.push(names.splice(nanoIndex, 1)[0])
|
names.push(names.splice(nanoIndex, 1)[0])
|
||||||
}
|
}
|
||||||
return names
|
return names
|
||||||
},
|
},
|
||||||
autoprefixerAndCssnanoLast (names) {
|
autoprefixerAndCssnanoLast (names: string[]) {
|
||||||
return orderPresets.cssnanoLast(orderPresets.autoprefixerLast(names))
|
return orderPresets.cssnanoLast(orderPresets.autoprefixerLast(names))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _postcssConfigFileWarningShown
|
export const getPostcssConfig = (nuxt: Nuxt) => {
|
||||||
function postcssConfigFileWarning () {
|
function defaultConfig () {
|
||||||
if (_postcssConfigFileWarningShown) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logger.warn('Please use `build.postcss` in your nuxt.config.js instead of an external config file. Support for such files will be removed in Nuxt 3 as they remove all defaults set by Nuxt and can cause severe problems with features like alias resolving inside your CSS.')
|
|
||||||
_postcssConfigFileWarningShown = true
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PostcssConfig {
|
|
||||||
nuxt: Nuxt
|
|
||||||
options: Nuxt['options']
|
|
||||||
|
|
||||||
constructor (nuxt) {
|
|
||||||
this.nuxt = nuxt
|
|
||||||
this.options = nuxt.options
|
|
||||||
}
|
|
||||||
|
|
||||||
get postcssOptions () {
|
|
||||||
return this.options.build.postcss.postcssOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
get postcssImportAlias () {
|
|
||||||
const alias = { ...this.options.alias }
|
|
||||||
|
|
||||||
for (const key in alias) {
|
|
||||||
if (key.startsWith('~')) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
const newKey = '~' + key
|
|
||||||
if (!alias[newKey]) {
|
|
||||||
alias[newKey] = alias[key]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return alias
|
|
||||||
}
|
|
||||||
|
|
||||||
get defaultConfig () {
|
|
||||||
const { dev, srcDir, rootDir, modulesDir } = this.options
|
|
||||||
return {
|
return {
|
||||||
sourceMap: this.options.build.cssSourceMap,
|
sourceMap: nuxt.options.webpack.cssSourceMap,
|
||||||
plugins: {
|
plugins: nuxt.options.postcss.plugins,
|
||||||
// https://github.com/postcss/postcss-import
|
|
||||||
'postcss-import': {
|
|
||||||
resolve: createResolver({
|
|
||||||
alias: this.postcssImportAlias,
|
|
||||||
modules: [srcDir, rootDir, ...modulesDir]
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// https://github.com/postcss/postcss-url
|
|
||||||
'postcss-url': {},
|
|
||||||
|
|
||||||
autoprefixer: {},
|
|
||||||
|
|
||||||
cssnano: dev
|
|
||||||
? false
|
|
||||||
: {
|
|
||||||
preset: ['default', {
|
|
||||||
// Keep quotes in font values to prevent from HEX conversion
|
|
||||||
// https://github.com/nuxt/nuxt.js/issues/6306
|
|
||||||
minifyFontValues: { removeQuotes: false }
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// Array, String or Function
|
// Array, String or Function
|
||||||
order: 'autoprefixerAndCssnanoLast'
|
order: 'autoprefixerAndCssnanoLast'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
searchConfigFile () {
|
function sortPlugins ({ plugins, order }) {
|
||||||
// Search for postCSS config file and use it if exists
|
|
||||||
// https://github.com/michael-ciniawsky/postcss-load-config
|
|
||||||
// TODO: Remove in Nuxt 3
|
|
||||||
const { srcDir, rootDir } = this.options
|
|
||||||
for (const dir of [srcDir, rootDir]) {
|
|
||||||
for (const file of [
|
|
||||||
'postcss.config.js',
|
|
||||||
'.postcssrc.js',
|
|
||||||
'.postcssrc',
|
|
||||||
'.postcssrc.json',
|
|
||||||
'.postcssrc.yaml'
|
|
||||||
]) {
|
|
||||||
const configFile = resolve(dir, file)
|
|
||||||
if (fs.existsSync(configFile)) {
|
|
||||||
postcssConfigFileWarning()
|
|
||||||
return configFile
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getConfigFile () {
|
|
||||||
const loaderConfig = this.postcssOptions && this.postcssOptions.config
|
|
||||||
const postcssConfigFile = loaderConfig || this.searchConfigFile()
|
|
||||||
|
|
||||||
if (typeof postcssConfigFile === 'string') {
|
|
||||||
return postcssConfigFile
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sortPlugins ({ plugins, order }) {
|
|
||||||
const names = Object.keys(plugins)
|
const names = Object.keys(plugins)
|
||||||
if (typeof order === 'string') {
|
if (typeof order === 'string') {
|
||||||
order = orderPresets[order]
|
order = orderPresets[order]
|
||||||
@ -138,11 +43,12 @@ export class PostcssConfig {
|
|||||||
return typeof order === 'function' ? order(names, orderPresets) : (order || names)
|
return typeof order === 'function' ? order(names, orderPresets) : (order || names)
|
||||||
}
|
}
|
||||||
|
|
||||||
loadPlugins (config) {
|
function loadPlugins (config) {
|
||||||
if (!isPureObject(config.plugins)) { return }
|
if (!isPureObject(config.plugins)) { return }
|
||||||
|
|
||||||
// Map postcss plugins into instances on object mode once
|
// Map postcss plugins into instances on object mode once
|
||||||
const cjs = createCommonJS(import.meta.url)
|
const cjs = createCommonJS(import.meta.url)
|
||||||
config.plugins = this.sortPlugins(config).map((pluginName) => {
|
config.plugins = sortPlugins(config).map((pluginName) => {
|
||||||
const pluginFn = requireModule(pluginName, { paths: [cjs.__dirname] })
|
const pluginFn = requireModule(pluginName, { paths: [cjs.__dirname] })
|
||||||
const pluginOptions = config.plugins[pluginName]
|
const pluginOptions = config.plugins[pluginName]
|
||||||
if (!pluginOptions || typeof pluginFn !== 'function') { return null }
|
if (!pluginOptions || typeof pluginFn !== 'function') { return null }
|
||||||
@ -150,41 +56,37 @@ export class PostcssConfig {
|
|||||||
}).filter(Boolean)
|
}).filter(Boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
config () {
|
if (!nuxt.options.webpack.postcss || !nuxt.options.postcss) {
|
||||||
/* istanbul ignore if */
|
return false
|
||||||
if (!this.options.build.postcss) {
|
}
|
||||||
return false
|
|
||||||
|
const configFile = nuxt.options.postcss?.config
|
||||||
|
if (configFile) {
|
||||||
|
return {
|
||||||
|
postcssOptions: {
|
||||||
|
config: configFile
|
||||||
|
},
|
||||||
|
sourceMap: nuxt.options.webpack.cssSourceMap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let postcssOptions = cloneDeep(nuxt.options.postcss)
|
||||||
|
// Apply default plugins
|
||||||
|
if (isPureObject(postcssOptions)) {
|
||||||
|
if (Array.isArray(postcssOptions.plugins)) {
|
||||||
|
defaults(postcssOptions, defaultConfig())
|
||||||
|
} else {
|
||||||
|
// Keep the order of default plugins
|
||||||
|
postcssOptions = merge({}, defaultConfig(), postcssOptions)
|
||||||
|
loadPlugins(postcssOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
const configFile = this.getConfigFile()
|
delete nuxt.options.webpack.postcss.order
|
||||||
if (configFile) {
|
|
||||||
return {
|
|
||||||
postcssOptions: {
|
|
||||||
config: configFile
|
|
||||||
},
|
|
||||||
sourceMap: this.options.build.cssSourceMap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let postcssOptions = cloneDeep(this.postcssOptions)
|
return {
|
||||||
|
sourceMap: nuxt.options.webpack.cssSourceMap,
|
||||||
// Apply default plugins
|
...nuxt.options.webpack.postcss,
|
||||||
if (isPureObject(postcssOptions)) {
|
postcssOptions
|
||||||
if (Array.isArray(postcssOptions.plugins)) {
|
|
||||||
defaults(postcssOptions, this.defaultConfig)
|
|
||||||
} else {
|
|
||||||
// Keep the order of default plugins
|
|
||||||
postcssOptions = merge({}, this.defaultConfig, postcssOptions)
|
|
||||||
this.loadPlugins(postcssOptions)
|
|
||||||
}
|
|
||||||
|
|
||||||
delete this.options.build.postcss.order
|
|
||||||
|
|
||||||
return {
|
|
||||||
sourceMap: this.options.build.cssSourceMap,
|
|
||||||
...this.options.build.postcss,
|
|
||||||
postcssOptions
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
export const reservedVueTags = [
|
|
||||||
// HTML tags
|
|
||||||
'html', 'body', 'base', 'head', 'link', 'meta', 'style', 'title', 'address',
|
|
||||||
'article', 'aside', 'footer', 'header', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
|
|
||||||
'hgroup', 'nav', 'section', 'div', 'dd', 'dl', 'dt', 'figcaption', 'figure',
|
|
||||||
'picture', 'hr', 'img', 'li', 'main', 'ol', 'p', 'pre', 'ul', 'a', 'b', 'abbr',
|
|
||||||
'bdi', 'bdo', 'br', 'cite', 'code', 'data', 'dfn', 'em', 'i', 'kbd', 'mark',
|
|
||||||
'q', 'rp', 'rt', 'rtc', 'ruby', 's', 'samp', 'small', 'span', 'strong', 'sub',
|
|
||||||
'sup', 'time', 'u', 'var', 'wbr', 'area', 'audio', 'map', 'track', 'video',
|
|
||||||
'embed', 'object', 'param', 'source', 'canvas', 'script', 'noscript', 'del',
|
|
||||||
'ins', 'caption', 'col', 'colgroup', 'table', 'thead', 'tbody', 'td', 'th', 'tr',
|
|
||||||
'button', 'datalist', 'fieldset', 'form', 'input', 'label', 'legend', 'meter',
|
|
||||||
'optgroup', 'option', 'output', 'progress', 'select', 'textarea', 'details',
|
|
||||||
'dialog', 'menu', 'menuitem', 'summary', 'content', 'element', 'shadow', 'template',
|
|
||||||
'blockquote', 'iframe', 'tfoot',
|
|
||||||
// SVG tags
|
|
||||||
'svg', 'animate', 'circle', 'clippath', 'cursor', 'defs', 'desc', 'ellipse', 'filter',
|
|
||||||
'font-face', 'foreignObject', 'g', 'glyph', 'image', 'line', 'marker', 'mask',
|
|
||||||
'missing-glyph', 'path', 'pattern', 'polygon', 'polyline', 'rect', 'switch', 'symbol',
|
|
||||||
'text', 'textpath', 'tspan', 'use', 'view',
|
|
||||||
// Vue built-in tags
|
|
||||||
'slot', 'component'
|
|
||||||
]
|
|
26
packages/webpack/src/virtual-modules.ts
Normal file
26
packages/webpack/src/virtual-modules.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { useNuxt } from '@nuxt/kit'
|
||||||
|
import VirtualModulesPlugin from 'webpack-virtual-modules'
|
||||||
|
|
||||||
|
export function registerVirtualModules () {
|
||||||
|
const nuxt = useNuxt()
|
||||||
|
|
||||||
|
// Initialize virtual modules instance
|
||||||
|
const virtualModules = new VirtualModulesPlugin(nuxt.vfs)
|
||||||
|
const writeFiles = () => {
|
||||||
|
for (const filePath in nuxt.vfs) {
|
||||||
|
virtualModules.writeModule(filePath, nuxt.vfs[filePath])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Workaround to initialize virtual modules
|
||||||
|
nuxt.hook('build:compile', ({ compiler }) => {
|
||||||
|
if (compiler.name === 'server') { writeFiles() }
|
||||||
|
})
|
||||||
|
// Update virtual modules when templates are updated
|
||||||
|
nuxt.hook('app:templatesGenerated', writeFiles)
|
||||||
|
|
||||||
|
nuxt.hook('webpack:config', configs => configs.forEach((config) => {
|
||||||
|
// Support virtual modules (input)
|
||||||
|
config.plugins.push(virtualModules)
|
||||||
|
}))
|
||||||
|
}
|
@ -1,302 +1,162 @@
|
|||||||
import type { IncomingMessage, ServerResponse } from 'http'
|
import type { IncomingMessage, ServerResponse } from 'http'
|
||||||
import { resolve } from 'pathe'
|
|
||||||
import pify from 'pify'
|
import pify from 'pify'
|
||||||
import webpack from 'webpack'
|
import webpack from 'webpack'
|
||||||
import Glob from 'glob'
|
import webpackDevMiddleware, { API } from 'webpack-dev-middleware'
|
||||||
import webpackDevMiddleware from 'webpack-dev-middleware'
|
|
||||||
import webpackHotMiddleware from 'webpack-hot-middleware'
|
import webpackHotMiddleware from 'webpack-hot-middleware'
|
||||||
import VirtualModulesPlugin from 'webpack-virtual-modules'
|
|
||||||
import { logger } from '@nuxt/kit'
|
|
||||||
import type { Compiler, Watching } from 'webpack'
|
import type { Compiler, Watching } from 'webpack'
|
||||||
import type { Context as WebpackDevMiddlewareContext, Options as WebpackDevMiddlewareOptions } from 'webpack-dev-middleware'
|
|
||||||
import type { MiddlewareOptions as WebpackHotMiddlewareOptions } from 'webpack-hot-middleware'
|
|
||||||
|
|
||||||
import type { Nuxt } from '@nuxt/schema'
|
import type { Nuxt } from '@nuxt/schema'
|
||||||
import { joinURL } from 'ufo'
|
import { joinURL } from 'ufo'
|
||||||
|
import { logger, useNuxt } from '@nuxt/kit'
|
||||||
import { DynamicBasePlugin } from '../../vite/src/plugins/dynamic-base'
|
import { DynamicBasePlugin } from '../../vite/src/plugins/dynamic-base'
|
||||||
import { createMFS } from './utils/mfs'
|
import { createMFS } from './utils/mfs'
|
||||||
|
import { registerVirtualModules } from './virtual-modules'
|
||||||
import { client, server } from './configs'
|
import { client, server } from './configs'
|
||||||
import { createWebpackConfigContext, applyPresets, getWebpackConfig } from './utils/config'
|
import { createWebpackConfigContext, applyPresets, getWebpackConfig } from './utils/config'
|
||||||
|
|
||||||
const glob = pify(Glob)
|
// TODO: Support plugins
|
||||||
class WebpackBundler {
|
// const plugins: string[] = []
|
||||||
nuxt: Nuxt
|
|
||||||
plugins: Array<string>
|
|
||||||
compilers: Array<Compiler>
|
|
||||||
compilersWatching: Array<Watching & { closeAsync?: () => void }>
|
|
||||||
// TODO: change this when pify has better types https://github.com/sindresorhus/pify/pull/76
|
|
||||||
devMiddleware: Record<string, Function & { close?: () => Promise<void>, context?: WebpackDevMiddlewareContext<IncomingMessage, ServerResponse> }>
|
|
||||||
hotMiddleware: Record<string, Function>
|
|
||||||
virtualModules: VirtualModulesPlugin
|
|
||||||
mfs?: Compiler['outputFileSystem']
|
|
||||||
__closed?: boolean
|
|
||||||
|
|
||||||
constructor (nuxt: Nuxt) {
|
export async function bundle (nuxt: Nuxt) {
|
||||||
this.nuxt = nuxt
|
await registerVirtualModules()
|
||||||
// TODO: plugins
|
|
||||||
this.plugins = []
|
|
||||||
|
|
||||||
// Class fields
|
|
||||||
this.compilers = []
|
|
||||||
this.compilersWatching = []
|
|
||||||
this.devMiddleware = {}
|
|
||||||
this.hotMiddleware = {}
|
|
||||||
|
|
||||||
// Bind middleware to self
|
|
||||||
this.middleware = this.middleware.bind(this)
|
|
||||||
|
|
||||||
// Initialize shared MFS for dev
|
|
||||||
if (this.nuxt.options.dev) {
|
|
||||||
this.mfs = createMFS() as Compiler['outputFileSystem']
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize virtual modules instance
|
|
||||||
this.virtualModules = new VirtualModulesPlugin(nuxt.vfs)
|
|
||||||
const writeFiles = () => {
|
|
||||||
for (const filePath in nuxt.vfs) {
|
|
||||||
this.virtualModules.writeModule(filePath, nuxt.vfs[filePath])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Workaround to initialize virtual modules
|
|
||||||
nuxt.hook('build:compile', ({ compiler }) => {
|
|
||||||
if (compiler.name === 'server') { writeFiles() }
|
|
||||||
})
|
|
||||||
// Update virtual modules when templates are updated
|
|
||||||
nuxt.hook('app:templatesGenerated', writeFiles)
|
|
||||||
}
|
|
||||||
|
|
||||||
getWebpackConfig (name) {
|
|
||||||
const ctx = createWebpackConfigContext({ nuxt: this.nuxt })
|
|
||||||
|
|
||||||
if (name === 'client') {
|
|
||||||
applyPresets(ctx, client)
|
|
||||||
} else if (name === 'server') {
|
|
||||||
applyPresets(ctx, server)
|
|
||||||
} else {
|
|
||||||
throw new Error(`Unsupported webpack config ${name}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const webpackConfigs = [client, ...nuxt.options.ssr ? [server] : []].map((preset) => {
|
||||||
|
const ctx = createWebpackConfigContext(nuxt)
|
||||||
|
applyPresets(ctx, preset)
|
||||||
return getWebpackConfig(ctx)
|
return getWebpackConfig(ctx)
|
||||||
}
|
})
|
||||||
|
|
||||||
async build () {
|
await nuxt.callHook('webpack:config', webpackConfigs)
|
||||||
const { options } = this.nuxt
|
|
||||||
|
|
||||||
const webpackConfigs = [
|
// Initialize shared MFS for dev
|
||||||
this.getWebpackConfig('client')
|
const mfs = nuxt.options.dev ? createMFS() : null
|
||||||
]
|
|
||||||
|
|
||||||
if (options.ssr) {
|
// Configure compilers
|
||||||
webpackConfigs.push(this.getWebpackConfig('server'))
|
const compilers = webpackConfigs.map((config) => {
|
||||||
|
config.plugins.push(DynamicBasePlugin.webpack({
|
||||||
|
env: nuxt.options.dev ? 'dev' : config.name as 'client',
|
||||||
|
devAppConfig: nuxt.options.app,
|
||||||
|
globalPublicPath: '__webpack_public_path__'
|
||||||
|
}))
|
||||||
|
|
||||||
|
// Create compiler
|
||||||
|
const compiler = webpack(config)
|
||||||
|
|
||||||
|
// In dev, write files in memory FS
|
||||||
|
if (nuxt.options.dev) {
|
||||||
|
compiler.outputFileSystem = mfs
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.nuxt.callHook('webpack:config', webpackConfigs)
|
return compiler
|
||||||
|
})
|
||||||
|
|
||||||
// Check styleResource existence
|
nuxt.hook('close', async () => {
|
||||||
const { styleResources } = this.nuxt.options.build
|
for (const compiler of compilers) {
|
||||||
if (styleResources && Object.keys(styleResources).length) {
|
|
||||||
logger.warn(
|
|
||||||
'Using styleResources without the @nuxtjs/style-resources is not suggested and can lead to severe performance issues.',
|
|
||||||
'Please use https://github.com/nuxt-community/style-resources-module'
|
|
||||||
)
|
|
||||||
for (const ext of Object.keys(styleResources)) {
|
|
||||||
await Promise.all(Array.from(styleResources[ext]).map(async (p) => {
|
|
||||||
const styleResourceFiles = await glob(resolve(this.nuxt.options.rootDir, p as string))
|
|
||||||
|
|
||||||
if (!styleResourceFiles || styleResourceFiles.length === 0) {
|
|
||||||
throw new Error(`Style Resource not found: ${p}`)
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure compilers
|
|
||||||
this.compilers = webpackConfigs.map((config) => {
|
|
||||||
// Support virtual modules (input)
|
|
||||||
config.plugins.push(this.virtualModules)
|
|
||||||
config.plugins.push(DynamicBasePlugin.webpack({
|
|
||||||
env: this.nuxt.options.dev ? 'dev' : config.name as 'client',
|
|
||||||
devAppConfig: this.nuxt.options.app,
|
|
||||||
globalPublicPath: '__webpack_public_path__'
|
|
||||||
}))
|
|
||||||
|
|
||||||
// Create compiler
|
|
||||||
const compiler = webpack(config)
|
|
||||||
|
|
||||||
// In dev, write files in memory FS
|
|
||||||
if (options.dev) {
|
|
||||||
compiler.outputFileSystem = this.mfs!
|
|
||||||
}
|
|
||||||
|
|
||||||
return compiler
|
|
||||||
})
|
|
||||||
|
|
||||||
// Start Builds
|
|
||||||
if (options.dev) {
|
|
||||||
return Promise.all(this.compilers.map(c => this.webpackCompile(c)))
|
|
||||||
} else {
|
|
||||||
for (const c of this.compilers) {
|
|
||||||
await this.webpackCompile(c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async webpackCompile (compiler) {
|
|
||||||
const { name } = compiler.options
|
|
||||||
const { options } = this.nuxt
|
|
||||||
|
|
||||||
await this.nuxt.callHook('build:compile', { name, compiler })
|
|
||||||
|
|
||||||
// Load renderer resources after build
|
|
||||||
compiler.hooks.done.tap('load-resources', async (stats) => {
|
|
||||||
await this.nuxt.callHook('build:compiled', {
|
|
||||||
name,
|
|
||||||
compiler,
|
|
||||||
stats
|
|
||||||
})
|
|
||||||
|
|
||||||
// Reload renderer
|
|
||||||
await this.nuxt.callHook('build:resources', this.mfs)
|
|
||||||
})
|
|
||||||
|
|
||||||
// --- Dev Build ---
|
|
||||||
if (options.dev) {
|
|
||||||
// Client build
|
|
||||||
if (['client', 'modern'].includes(name)) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
compiler.hooks.done.tap('nuxt-dev', () => { resolve(null) })
|
|
||||||
compiler.hooks.failed.tap('nuxt-errorlog', (err) => { reject(err) })
|
|
||||||
// Start watch
|
|
||||||
this.webpackDev(compiler)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Server, build and watch for changes
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const watching = compiler.watch(options.watchers.webpack, (err) => {
|
|
||||||
if (err) {
|
|
||||||
return reject(err)
|
|
||||||
}
|
|
||||||
resolve(null)
|
|
||||||
})
|
|
||||||
|
|
||||||
watching.closeAsync = pify(watching.close)
|
|
||||||
this.compilersWatching.push(watching)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Production Build ---
|
|
||||||
compiler.run = pify(compiler.run)
|
|
||||||
const stats = await compiler.run()
|
|
||||||
|
|
||||||
if (stats.hasErrors()) {
|
|
||||||
// non-quiet mode: errors will be printed by webpack itself
|
|
||||||
const error = new Error('Nuxt build error')
|
|
||||||
if (options.build.quiet === true) {
|
|
||||||
error.stack = stats.toString('errors-only')
|
|
||||||
}
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Await for renderer to load resources (programmatic, tests and generate)
|
|
||||||
await this.nuxt.callHook('build:resources')
|
|
||||||
}
|
|
||||||
|
|
||||||
async webpackDev (compiler: Compiler) {
|
|
||||||
logger.debug('Creating webpack middleware...')
|
|
||||||
|
|
||||||
const { name } = compiler.options
|
|
||||||
const buildOptions = this.nuxt.options.build
|
|
||||||
const { client, ...hotMiddlewareOptions } = buildOptions.hotMiddleware || {}
|
|
||||||
|
|
||||||
// Create webpack dev middleware
|
|
||||||
this.devMiddleware[name] = pify(
|
|
||||||
// @ts-ignore
|
|
||||||
webpackDevMiddleware(
|
|
||||||
// @ts-ignore
|
|
||||||
compiler,
|
|
||||||
{
|
|
||||||
publicPath: joinURL(this.nuxt.options.app.baseURL, this.nuxt.options.app.buildAssetsDir),
|
|
||||||
outputFileSystem: this.mfs,
|
|
||||||
stats: 'none',
|
|
||||||
...buildOptions.devMiddleware
|
|
||||||
} as WebpackDevMiddlewareOptions<IncomingMessage, ServerResponse>
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
this.devMiddleware[name].close = pify(this.devMiddleware[name].close)
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
this.compilersWatching.push(this.devMiddleware[name].context.watching)
|
|
||||||
|
|
||||||
this.hotMiddleware[name] = pify(
|
|
||||||
webpackHotMiddleware(
|
|
||||||
compiler as any,
|
|
||||||
{
|
|
||||||
log: false,
|
|
||||||
heartbeat: 10000,
|
|
||||||
path: joinURL(this.nuxt.options.app.baseURL, '__webpack_hmr', name),
|
|
||||||
...hotMiddlewareOptions
|
|
||||||
} as WebpackHotMiddlewareOptions
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Register devMiddleware on server
|
|
||||||
await this.nuxt.callHook('server:devMiddleware', this.middleware)
|
|
||||||
}
|
|
||||||
|
|
||||||
async middleware (req: IncomingMessage, res: ServerResponse, next: () => any) {
|
|
||||||
if (this.devMiddleware && this.devMiddleware.client) {
|
|
||||||
await this.devMiddleware.client(req, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.hotMiddleware && this.hotMiddleware.client) {
|
|
||||||
await this.hotMiddleware.client(req, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
next()
|
|
||||||
}
|
|
||||||
|
|
||||||
async unwatch () {
|
|
||||||
await Promise.all(this.compilersWatching.map(watching => watching.closeAsync()))
|
|
||||||
}
|
|
||||||
|
|
||||||
async close () {
|
|
||||||
if (this.__closed) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.__closed = true
|
|
||||||
|
|
||||||
// Unwatch
|
|
||||||
await this.unwatch()
|
|
||||||
|
|
||||||
// Stop webpack middleware
|
|
||||||
for (const devMiddleware of Object.values(this.devMiddleware)) {
|
|
||||||
await devMiddleware.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const compiler of this.compilers) {
|
|
||||||
await new Promise(resolve => compiler.close(resolve))
|
await new Promise(resolve => compiler.close(resolve))
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// Cleanup MFS
|
// Start Builds
|
||||||
if (this.mfs) {
|
if (nuxt.options.dev) {
|
||||||
delete this.mfs
|
return Promise.all(compilers.map(c => compile(c)))
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const c of compilers) {
|
||||||
|
await compile(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createDevMiddleware (compiler: Compiler) {
|
||||||
|
const nuxt = useNuxt()
|
||||||
|
|
||||||
|
logger.debug('Creating webpack middleware...')
|
||||||
|
|
||||||
|
// Create webpack dev middleware
|
||||||
|
const devMiddleware = pify(webpackDevMiddleware(compiler, {
|
||||||
|
publicPath: joinURL(nuxt.options.app.baseURL, nuxt.options.app.buildAssetsDir),
|
||||||
|
outputFileSystem: compiler.outputFileSystem as any,
|
||||||
|
stats: 'none',
|
||||||
|
...nuxt.options.webpack.devMiddleware
|
||||||
|
})) as API<IncomingMessage, ServerResponse>
|
||||||
|
|
||||||
|
nuxt.hook('close', () => pify(devMiddleware.close.bind(devMiddleware))())
|
||||||
|
|
||||||
|
const { client: _client, ...hotMiddlewareOptions } = nuxt.options.webpack.hotMiddleware || {}
|
||||||
|
const hotMiddleware = pify(webpackHotMiddleware(compiler, {
|
||||||
|
log: false,
|
||||||
|
heartbeat: 10000,
|
||||||
|
path: joinURL(nuxt.options.app.baseURL, '__webpack_hmr', compiler.options.name),
|
||||||
|
...hotMiddlewareOptions
|
||||||
|
}))
|
||||||
|
|
||||||
|
// Register devMiddleware on server
|
||||||
|
await nuxt.callHook('server:devMiddleware', async (req, res, next) => {
|
||||||
|
for (const mw of [devMiddleware, hotMiddleware]) {
|
||||||
|
await mw?.(req, res)
|
||||||
|
}
|
||||||
|
next()
|
||||||
|
})
|
||||||
|
|
||||||
|
return devMiddleware
|
||||||
|
}
|
||||||
|
|
||||||
|
async function compile (compiler: Compiler) {
|
||||||
|
const nuxt = useNuxt()
|
||||||
|
|
||||||
|
const { name } = compiler.options
|
||||||
|
|
||||||
|
await nuxt.callHook('build:compile', { name, compiler })
|
||||||
|
|
||||||
|
// Load renderer resources after build
|
||||||
|
compiler.hooks.done.tap('load-resources', async (stats) => {
|
||||||
|
await nuxt.callHook('build:compiled', { name, compiler, stats })
|
||||||
|
// Reload renderer
|
||||||
|
await nuxt.callHook('build:resources', compiler.outputFileSystem)
|
||||||
|
})
|
||||||
|
|
||||||
|
// --- Dev Build ---
|
||||||
|
if (nuxt.options.dev) {
|
||||||
|
const compilersWatching: Watching[] = []
|
||||||
|
|
||||||
|
nuxt.hook('close', async () => {
|
||||||
|
await Promise.all(compilersWatching.map(watching => pify(watching.close.bind(watching))()))
|
||||||
|
})
|
||||||
|
|
||||||
|
// Client build
|
||||||
|
if (name === 'client') {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
compiler.hooks.done.tap('nuxt-dev', () => { resolve(null) })
|
||||||
|
compiler.hooks.failed.tap('nuxt-errorlog', (err) => { reject(err) })
|
||||||
|
// Start watch
|
||||||
|
createDevMiddleware(compiler).then((devMiddleware) => {
|
||||||
|
compilersWatching.push(devMiddleware.context.watching)
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup more resources
|
// Server, build and watch for changes
|
||||||
delete this.compilers
|
return new Promise((resolve, reject) => {
|
||||||
delete this.compilersWatching
|
const watching = compiler.watch(nuxt.options.watchers.webpack, (err) => {
|
||||||
delete this.devMiddleware
|
if (err) { return reject(err) }
|
||||||
delete this.hotMiddleware
|
resolve(null)
|
||||||
|
})
|
||||||
|
|
||||||
|
compilersWatching.push(watching)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
forGenerate () {
|
// --- Production Build ---
|
||||||
this.nuxt.options.target = 'static'
|
const stats = await new Promise<webpack.Stats>((resolve, reject) => compiler.run((err, stats) => err ? reject(err) : resolve(stats)))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function bundle (nuxt: Nuxt) {
|
if (stats.hasErrors()) {
|
||||||
const bundler = new WebpackBundler(nuxt)
|
// non-quiet mode: errors will be printed by webpack itself
|
||||||
return bundler.build()
|
const error = new Error('Nuxt build error')
|
||||||
|
if (nuxt.options.build.quiet === true) {
|
||||||
|
error.stack = stats.toString('errors-only')
|
||||||
|
}
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Await for renderer to load resources (programmatic, tests and generate)
|
||||||
|
await nuxt.callHook('build:resources')
|
||||||
}
|
}
|
||||||
|
2
test/fixtures/basic/nuxt.config.ts
vendored
2
test/fixtures/basic/nuxt.config.ts
vendored
@ -3,7 +3,7 @@ import { addComponent } from '@nuxt/kit'
|
|||||||
|
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
buildDir: process.env.NITRO_BUILD_DIR,
|
buildDir: process.env.NITRO_BUILD_DIR,
|
||||||
vite: !process.env.TEST_WITH_WEBPACK,
|
builder: process.env.TEST_WITH_WEBPACK ? 'webpack' : 'vite',
|
||||||
nitro: {
|
nitro: {
|
||||||
output: { dir: process.env.NITRO_OUTPUT_DIR }
|
output: { dir: process.env.NITRO_OUTPUT_DIR }
|
||||||
},
|
},
|
||||||
|
61
yarn.lock
61
yarn.lock
@ -3163,6 +3163,7 @@ __metadata:
|
|||||||
defu: ^5.0.1
|
defu: ^5.0.1
|
||||||
jiti: ^1.13.0
|
jiti: ^1.13.0
|
||||||
pathe: ^0.2.0
|
pathe: ^0.2.0
|
||||||
|
postcss-import-resolver: ^2.0.0
|
||||||
scule: ^0.2.1
|
scule: ^0.2.1
|
||||||
std-env: ^3.0.1
|
std-env: ^3.0.1
|
||||||
ufo: ^0.7.9
|
ufo: ^0.7.9
|
||||||
@ -3393,7 +3394,6 @@ __metadata:
|
|||||||
p-debounce: ^4.0.0
|
p-debounce: ^4.0.0
|
||||||
pathe: ^0.2.0
|
pathe: ^0.2.0
|
||||||
postcss-import: ^14.0.2
|
postcss-import: ^14.0.2
|
||||||
postcss-import-resolver: ^2.0.0
|
|
||||||
postcss-url: ^10.1.3
|
postcss-url: ^10.1.3
|
||||||
rollup-plugin-visualizer: ^5.6.0
|
rollup-plugin-visualizer: ^5.6.0
|
||||||
ufo: ^0.7.9
|
ufo: ^0.7.9
|
||||||
@ -3480,7 +3480,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@nuxt/webpack-builder@3.0.0, @nuxt/webpack-builder@workspace:packages/webpack":
|
"@nuxt/webpack-builder@workspace:packages/webpack":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@nuxt/webpack-builder@workspace:packages/webpack"
|
resolution: "@nuxt/webpack-builder@workspace:packages/webpack"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -3489,14 +3489,11 @@ __metadata:
|
|||||||
"@nuxt/kit": 3.0.0
|
"@nuxt/kit": 3.0.0
|
||||||
"@nuxt/schema": 3.0.0
|
"@nuxt/schema": 3.0.0
|
||||||
"@types/pify": ^5.0.1
|
"@types/pify": ^5.0.1
|
||||||
"@types/terser-webpack-plugin": ^5.0.4
|
|
||||||
"@types/webpack-bundle-analyzer": ^4.4.1
|
"@types/webpack-bundle-analyzer": ^4.4.1
|
||||||
"@types/webpack-dev-middleware": ^5.0.2
|
"@types/webpack-dev-middleware": ^5.0.2
|
||||||
"@types/webpack-hot-middleware": ^2.25.6
|
"@types/webpack-hot-middleware": ^2.25.6
|
||||||
"@types/webpack-virtual-modules": ^0
|
"@types/webpack-virtual-modules": ^0
|
||||||
"@vue/babel-preset-jsx": ^1.2.4
|
|
||||||
autoprefixer: ^10.4.2
|
autoprefixer: ^10.4.2
|
||||||
babel-loader: ^8.2.3
|
|
||||||
css-loader: ^6.6.0
|
css-loader: ^6.6.0
|
||||||
css-minimizer-webpack-plugin: ^3.4.1
|
css-minimizer-webpack-plugin: ^3.4.1
|
||||||
cssnano: ^5.0.17
|
cssnano: ^5.0.17
|
||||||
@ -3504,7 +3501,6 @@ __metadata:
|
|||||||
escape-string-regexp: ^5.0.0
|
escape-string-regexp: ^5.0.0
|
||||||
file-loader: ^6.2.0
|
file-loader: ^6.2.0
|
||||||
fs-extra: ^10.0.1
|
fs-extra: ^10.0.1
|
||||||
glob: ^7.2.0
|
|
||||||
hash-sum: ^2.0.0
|
hash-sum: ^2.0.0
|
||||||
lodash-es: ^4.17.21
|
lodash-es: ^4.17.21
|
||||||
memfs: ^3.4.1
|
memfs: ^3.4.1
|
||||||
@ -3514,7 +3510,6 @@ __metadata:
|
|||||||
pify: ^5.0.0
|
pify: ^5.0.0
|
||||||
postcss: ^8.4.7
|
postcss: ^8.4.7
|
||||||
postcss-import: ^14.0.2
|
postcss-import: ^14.0.2
|
||||||
postcss-import-resolver: ^2.0.0
|
|
||||||
postcss-loader: ^6.2.1
|
postcss-loader: ^6.2.1
|
||||||
postcss-url: ^10.1.3
|
postcss-url: ^10.1.3
|
||||||
style-resources-loader: ^1.5.0
|
style-resources-loader: ^1.5.0
|
||||||
@ -4630,16 +4625,6 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@types/terser-webpack-plugin@npm:^5.0.4":
|
|
||||||
version: 5.0.4
|
|
||||||
resolution: "@types/terser-webpack-plugin@npm:5.0.4"
|
|
||||||
dependencies:
|
|
||||||
terser: ^5.3.8
|
|
||||||
webpack: ^5.1.0
|
|
||||||
checksum: 7b3845526d4ed7b636f7b2f8f35b5d7e45211f7a55afc85e32a66655eaf65cd193e2fec195bcdb473c0d9a5b2828798b9c23196fdc86e9cd2e9420227012f438
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@types/throttle-debounce@npm:^2.1.0":
|
"@types/throttle-debounce@npm:^2.1.0":
|
||||||
version: 2.1.0
|
version: 2.1.0
|
||||||
resolution: "@types/throttle-debounce@npm:2.1.0"
|
resolution: "@types/throttle-debounce@npm:2.1.0"
|
||||||
@ -15675,7 +15660,6 @@ __metadata:
|
|||||||
"@nuxt/nitro": 3.0.0
|
"@nuxt/nitro": 3.0.0
|
||||||
"@nuxt/schema": 3.0.0
|
"@nuxt/schema": 3.0.0
|
||||||
"@nuxt/vite-builder": 3.0.0
|
"@nuxt/vite-builder": 3.0.0
|
||||||
"@nuxt/webpack-builder": 3.0.0
|
|
||||||
"@types/fs-extra": ^9.0.13
|
"@types/fs-extra": ^9.0.13
|
||||||
"@types/hash-sum": ^1.0.0
|
"@types/hash-sum": ^1.0.0
|
||||||
"@vue/reactivity": ^3.2.31
|
"@vue/reactivity": ^3.2.31
|
||||||
@ -20771,7 +20755,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"terser@npm:^5.0.0, terser@npm:^5.3.4, terser@npm:^5.3.8, terser@npm:^5.7.2":
|
"terser@npm:^5.0.0, terser@npm:^5.3.4, terser@npm:^5.7.2":
|
||||||
version: 5.10.0
|
version: 5.10.0
|
||||||
resolution: "terser@npm:5.10.0"
|
resolution: "terser@npm:5.10.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -22553,44 +22537,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"webpack@npm:^5, webpack@npm:^5.1.0, webpack@npm:^5.38.1":
|
"webpack@npm:^5, webpack@npm:^5.38.1, webpack@npm:^5.69.1":
|
||||||
version: 5.69.0
|
|
||||||
resolution: "webpack@npm:5.69.0"
|
|
||||||
dependencies:
|
|
||||||
"@types/eslint-scope": ^3.7.3
|
|
||||||
"@types/estree": ^0.0.51
|
|
||||||
"@webassemblyjs/ast": 1.11.1
|
|
||||||
"@webassemblyjs/wasm-edit": 1.11.1
|
|
||||||
"@webassemblyjs/wasm-parser": 1.11.1
|
|
||||||
acorn: ^8.4.1
|
|
||||||
acorn-import-assertions: ^1.7.6
|
|
||||||
browserslist: ^4.14.5
|
|
||||||
chrome-trace-event: ^1.0.2
|
|
||||||
enhanced-resolve: ^5.9.0
|
|
||||||
es-module-lexer: ^0.9.0
|
|
||||||
eslint-scope: 5.1.1
|
|
||||||
events: ^3.2.0
|
|
||||||
glob-to-regexp: ^0.4.1
|
|
||||||
graceful-fs: ^4.2.9
|
|
||||||
json-parse-better-errors: ^1.0.2
|
|
||||||
loader-runner: ^4.2.0
|
|
||||||
mime-types: ^2.1.27
|
|
||||||
neo-async: ^2.6.2
|
|
||||||
schema-utils: ^3.1.0
|
|
||||||
tapable: ^2.1.1
|
|
||||||
terser-webpack-plugin: ^5.1.3
|
|
||||||
watchpack: ^2.3.1
|
|
||||||
webpack-sources: ^3.2.3
|
|
||||||
peerDependenciesMeta:
|
|
||||||
webpack-cli:
|
|
||||||
optional: true
|
|
||||||
bin:
|
|
||||||
webpack: bin/webpack.js
|
|
||||||
checksum: 0b0fc2ffcb926fc7506ec56901ae9a69f1ae969a6afc63395a3ed56f938d385c1d16d1dea39fd56dbb9362189c05da49174219904e5a337040aed5a46080e926
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"webpack@npm:^5.69.1":
|
|
||||||
version: 5.69.1
|
version: 5.69.1
|
||||||
resolution: "webpack@npm:5.69.1"
|
resolution: "webpack@npm:5.69.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
Loading…
Reference in New Issue
Block a user