mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 15:15:19 +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) {
|
||||
// @ts-ignore
|
||||
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) {
|
||||
|
@ -35,7 +35,6 @@
|
||||
"@nuxt/nitro": "3.0.0",
|
||||
"@nuxt/schema": "3.0.0",
|
||||
"@nuxt/vite-builder": "3.0.0",
|
||||
"@nuxt/webpack-builder": "3.0.0",
|
||||
"@vue/reactivity": "^3.2.31",
|
||||
"@vue/shared": "^3.2.31",
|
||||
"@vueuse/head": "^0.7.5",
|
||||
|
@ -1,5 +1,6 @@
|
||||
import chokidar from 'chokidar'
|
||||
import type { Nuxt } from '@nuxt/schema'
|
||||
import { tryImportModule } from '@nuxt/kit'
|
||||
import { createApp, generateApp } from './app'
|
||||
|
||||
export async function build (nuxt: Nuxt) {
|
||||
@ -48,8 +49,9 @@ function watch (nuxt: Nuxt) {
|
||||
}
|
||||
|
||||
async function bundle (nuxt: Nuxt) {
|
||||
const useVite = nuxt.options.vite !== false
|
||||
const { bundle } = await (useVite ? import('@nuxt/vite-builder') : import('@nuxt/webpack-builder'))
|
||||
const { bundle } = typeof nuxt.options.builder === 'string'
|
||||
? await tryImportModule(nuxt.options.builder, { paths: nuxt.options.rootDir })
|
||||
: nuxt.options.builder
|
||||
try {
|
||||
return bundle(nuxt)
|
||||
} catch (error) {
|
||||
|
@ -9,7 +9,10 @@ export default defineBuildConfig({
|
||||
name: 'config',
|
||||
builder: 'untyped',
|
||||
defaults: {
|
||||
rootDir: '/<rootDir>/'
|
||||
rootDir: '/<rootDir>/',
|
||||
vite: {
|
||||
base: '/'
|
||||
}
|
||||
}
|
||||
},
|
||||
'src/index'
|
||||
@ -24,6 +27,12 @@ export default defineBuildConfig({
|
||||
'webpack-bundle-analyzer',
|
||||
'rollup-plugin-visualizer',
|
||||
'vite',
|
||||
'mini-css-extract-plugin',
|
||||
'terser-webpack-plugin',
|
||||
'css-minimizer-webpack-plugin',
|
||||
'webpack-dev-middleware',
|
||||
'webpack-hot-middleware',
|
||||
'postcss',
|
||||
'consola',
|
||||
// Implicit
|
||||
'@vue/compiler-core',
|
||||
|
@ -24,6 +24,7 @@
|
||||
"defu": "^5.0.1",
|
||||
"jiti": "^1.13.0",
|
||||
"pathe": "^0.2.0",
|
||||
"postcss-import-resolver": "^2.0.0",
|
||||
"scule": "^0.2.1",
|
||||
"std-env": "^3.0.1",
|
||||
"ufo": "^0.7.9"
|
||||
|
@ -1,8 +1,28 @@
|
||||
import defu from 'defu'
|
||||
import { join } from 'pathe'
|
||||
import { isCI, isTest } from 'std-env'
|
||||
import { normalizeURL, withTrailingSlash } from 'ufo'
|
||||
|
||||
export default {
|
||||
/**
|
||||
* The builder to use for bundling the Vue part of your application.
|
||||
*
|
||||
* @type {'vite' | 'webpack' | { bundle: (nuxt: typeof import('../src/types/nuxt').Nuxt) => Promise<void> }}
|
||||
*/
|
||||
builder: {
|
||||
$resolve: (val, get) => {
|
||||
if (typeof val === 'object') {
|
||||
return val
|
||||
}
|
||||
const map = {
|
||||
vite: '@nuxt/vite-builder',
|
||||
webpack: '@nuxt/webpack-builder',
|
||||
}
|
||||
return map[val] || (get('vite') === false ? map.webpack : map.vite)
|
||||
},
|
||||
},
|
||||
|
||||
build: {
|
||||
/**
|
||||
* Suppresses most of the build output log.
|
||||
*
|
||||
@ -10,6 +30,7 @@ export default {
|
||||
*
|
||||
* @see [std-env](https://github.com/unjs/std-env)
|
||||
* @version 2
|
||||
* @version 3
|
||||
*/
|
||||
quiet: Boolean(isCI || isTest),
|
||||
|
||||
@ -98,14 +119,12 @@ export default {
|
||||
* }
|
||||
* ```
|
||||
* @version 2
|
||||
* @version 3 webpack only
|
||||
*/
|
||||
extractCSS: false,
|
||||
|
||||
/**
|
||||
* Enables CSS source map support (defaults to true in development)
|
||||
* @version 2
|
||||
* @version 3 webpack only
|
||||
*/
|
||||
cssSourceMap: {
|
||||
$resolve: (val, get) => val ?? get('dev')
|
||||
@ -176,7 +195,6 @@ export default {
|
||||
*
|
||||
* Defaults to `'url'` ([see package](https://www.npmjs.com/package/url)).
|
||||
* @version 2
|
||||
* @version 3 webpack only
|
||||
*/
|
||||
serverURLPolyfill: 'url',
|
||||
|
||||
@ -197,7 +215,6 @@ export default {
|
||||
* }
|
||||
* ```
|
||||
* @version 2
|
||||
* @version 3 webpack only
|
||||
*/
|
||||
filenames: {
|
||||
app: ({ isDev, isModern }) => isDev ? `[name]${isModern ? '.modern' : ''}.js` : `[contenthash:7]${isModern ? '.modern' : ''}.js`,
|
||||
@ -211,7 +228,6 @@ export default {
|
||||
/**
|
||||
* Customize the options of Nuxt's integrated webpack loaders.
|
||||
* @version 2
|
||||
* @version 3 webpack only
|
||||
*/
|
||||
loaders: {
|
||||
$resolve: (val, get) => {
|
||||
@ -284,7 +300,6 @@ export default {
|
||||
* ]
|
||||
* ```
|
||||
* @version 2
|
||||
* @version 3 webpack only
|
||||
*/
|
||||
plugins: [],
|
||||
|
||||
@ -298,7 +313,6 @@ export default {
|
||||
* @note Enabling sourceMap will leave `//# sourceMappingURL` linking comment at
|
||||
* the end of each output file if webpack `config.devtool` is set to `source-map`.
|
||||
* @version 2
|
||||
* @version 3 webpack only
|
||||
*/
|
||||
terser: {},
|
||||
|
||||
@ -313,7 +327,6 @@ export default {
|
||||
/**
|
||||
* Hard-replaces `typeof process`, `typeof window` and `typeof document` to tree-shake bundle.
|
||||
* @version 2
|
||||
* @version 3 webpack only
|
||||
*/
|
||||
aggressiveCodeRemoval: false,
|
||||
|
||||
@ -324,7 +337,6 @@ export default {
|
||||
*
|
||||
* @see [optimize-css-assets-webpack-plugin documentation](https://github.com/NMFR/optimize-css-assets-webpack-plugin).
|
||||
* @version 2
|
||||
* @version 3 webpack only
|
||||
*/
|
||||
optimizeCSS: {
|
||||
$resolve: (val, get) => val ?? (get('build.extractCSS') ? {} : false)
|
||||
@ -333,7 +345,6 @@ export default {
|
||||
/**
|
||||
* Configure [webpack optimization](https://webpack.js.org/configuration/optimization/).
|
||||
* @version 2
|
||||
* @version 3 webpack only
|
||||
*/
|
||||
optimization: {
|
||||
runtimeChunk: 'single',
|
||||
@ -364,7 +375,6 @@ export default {
|
||||
* Nuxt will automatically detect the current version of `core-js` in your project (`'auto'`),
|
||||
* or you can specify which version you want to use (`2` or `3`).
|
||||
* @version 2
|
||||
* @version 3 webpack only
|
||||
*/
|
||||
corejs: 'auto',
|
||||
|
||||
@ -376,7 +386,6 @@ export default {
|
||||
*
|
||||
* @note `.babelrc` is ignored by default.
|
||||
* @version 2
|
||||
* @version 3 webpack only
|
||||
*/
|
||||
babel: {
|
||||
configFile: false,
|
||||
@ -467,13 +476,17 @@ export default {
|
||||
* Customize PostCSS Loader plugins.
|
||||
* Sames options as https://github.com/webpack-contrib/postcss-loader#options
|
||||
* @version 2
|
||||
* @version 3 webpack only
|
||||
*/
|
||||
postcss: {
|
||||
execute: undefined,
|
||||
postcssOptions: {
|
||||
config: undefined,
|
||||
plugins: undefined
|
||||
$resolve: (val, get) => {
|
||||
// Ensure we return the same object in `build.postcss.postcssOptions as `postcss`
|
||||
// so modules which modify the configuration continue to work.
|
||||
const postcssOptions = get('postcss')
|
||||
Object.assign(postcssOptions, defu(postcssOptions, val))
|
||||
return postcssOptions
|
||||
}
|
||||
},
|
||||
sourceMap: undefined,
|
||||
implementation: undefined,
|
||||
@ -564,7 +577,6 @@ export default {
|
||||
/**
|
||||
* See [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) for available options.
|
||||
* @version 2
|
||||
* @version 3 webpack only
|
||||
*/
|
||||
devMiddleware: {
|
||||
stats: 'none'
|
||||
@ -572,7 +584,6 @@ export default {
|
||||
/**
|
||||
* See [webpack-hot-middleware](https://github.com/webpack-contrib/webpack-hot-middleware) for available options.
|
||||
* @version 2
|
||||
* @version 3 webpack only
|
||||
*/
|
||||
hotMiddleware: {},
|
||||
|
||||
@ -598,7 +609,6 @@ export default {
|
||||
/**
|
||||
* Set to `false` to disable the overlay provided by [FriendlyErrorsWebpackPlugin](https://github.com/nuxt/friendly-errors-webpack-plugin)
|
||||
* @version 2
|
||||
* @version 3 webpack only
|
||||
*/
|
||||
friendlyErrors: true,
|
||||
/**
|
||||
@ -609,7 +619,6 @@ export default {
|
||||
/**
|
||||
* Filters to hide build warnings.
|
||||
* @version 2
|
||||
* @version 3 webpack only
|
||||
*/
|
||||
warningIgnoreFilters: [],
|
||||
|
||||
@ -617,6 +626,6 @@ export default {
|
||||
* Set to true to scan files within symlinks in the build (such as within `pages/`).
|
||||
* @version 2
|
||||
*/
|
||||
|
||||
followSymlinks: false
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,10 @@ import router from './router'
|
||||
import server from './server'
|
||||
import cli from './cli'
|
||||
import generate from './generate'
|
||||
import postcss from './postcss'
|
||||
import typescript from './typescript'
|
||||
import vite from './vite'
|
||||
import webpack from './webpack'
|
||||
import nitro from './nitro'
|
||||
import experimental from './experimental'
|
||||
|
||||
@ -37,25 +40,18 @@ export default {
|
||||
..._app,
|
||||
..._common,
|
||||
..._internal,
|
||||
...postcss,
|
||||
...typescript,
|
||||
...vite,
|
||||
...webpack,
|
||||
...nitro,
|
||||
build,
|
||||
// Legacy
|
||||
...build,
|
||||
messages,
|
||||
render,
|
||||
router,
|
||||
server,
|
||||
cli,
|
||||
generate,
|
||||
typescript,
|
||||
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,4 +1,5 @@
|
||||
export default {
|
||||
typescript: {
|
||||
/**
|
||||
* 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.
|
||||
@ -18,4 +19,5 @@ export default {
|
||||
* 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
|
||||
}
|
||||
}
|
||||
|
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. */
|
||||
extendBuild(fn): void
|
||||
|
||||
/** Allows extending routes by chaining `options.build.extendRoutes` function. */
|
||||
/** Allows extending routes by chaining `options.router.extendRoutes` function. */
|
||||
extendRoutes(fn): void
|
||||
|
||||
/** Registers a module */
|
||||
|
@ -35,7 +35,6 @@
|
||||
"p-debounce": "^4.0.0",
|
||||
"pathe": "^0.2.0",
|
||||
"postcss-import": "^14.0.2",
|
||||
"postcss-import-resolver": "^2.0.0",
|
||||
"postcss-url": "^10.1.3",
|
||||
"rollup-plugin-visualizer": "^5.6.0",
|
||||
"ufo": "^0.7.9",
|
||||
|
@ -1,8 +1,6 @@
|
||||
import createResolver from 'postcss-import-resolver'
|
||||
import defu from 'defu'
|
||||
import { requireModule } from '@nuxt/kit'
|
||||
import type { Nuxt } from '@nuxt/schema'
|
||||
import { ViteOptions } from './vite'
|
||||
import type { ViteOptions } from './vite'
|
||||
import { distDir } from './dirs'
|
||||
|
||||
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, {
|
||||
// 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: {}
|
||||
})
|
||||
const plugins = nuxt.options.postcss.plugins
|
||||
|
||||
for (const name in plugins) {
|
||||
const opts = plugins[name]
|
||||
|
@ -5,7 +5,6 @@ import type { InlineConfig, SSROptions } from 'vite'
|
||||
import { logger } from '@nuxt/kit'
|
||||
import type { Options } from '@vitejs/plugin-vue'
|
||||
import { sanitizeFilePath } from 'mlly'
|
||||
import { joinURL, withoutLeadingSlash } from 'ufo'
|
||||
import { getPort } from 'get-port-please'
|
||||
import { buildClient } from './client'
|
||||
import { buildServer } from './server'
|
||||
@ -35,14 +34,7 @@ export async function bundle (nuxt: Nuxt) {
|
||||
nuxt,
|
||||
config: vite.mergeConfig(
|
||||
{
|
||||
root: nuxt.options.srcDir,
|
||||
mode: nuxt.options.dev ? 'development' : 'production',
|
||||
logLevel: 'warn',
|
||||
define: {
|
||||
'process.dev': nuxt.options.dev
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
|
||||
alias: {
|
||||
...nuxt.options.alias,
|
||||
'#app': nuxt.options.appDir,
|
||||
@ -56,37 +48,16 @@ export async function bundle (nuxt: Nuxt) {
|
||||
'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: {
|
||||
exclude: [
|
||||
...nuxt.options.build.transpile.filter(i => typeof i === 'string'),
|
||||
'vue-demi'
|
||||
],
|
||||
entries: [
|
||||
resolve(nuxt.options.appDir, 'entry.ts')
|
||||
]
|
||||
},
|
||||
esbuild: {
|
||||
jsxFactory: 'h',
|
||||
jsxFragment: 'Fragment',
|
||||
tsconfigRaw: '{}'
|
||||
},
|
||||
clearScreen: false,
|
||||
css: resolveCSSOptions(nuxt),
|
||||
build: {
|
||||
assetsDir: nuxt.options.dev ? withoutLeadingSlash(nuxt.options.app.buildAssetsDir) : '.',
|
||||
emptyOutDir: false,
|
||||
rollupOptions: {
|
||||
input: resolve(nuxt.options.appDir, 'entry'),
|
||||
output: { sanitizeFileName: sanitizeFilePath }
|
||||
output: { sanitizeFileName: sanitizeFilePath },
|
||||
input: resolve(nuxt.options.appDir, 'entry')
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
@ -98,18 +69,13 @@ export async function bundle (nuxt: Nuxt) {
|
||||
port: hmrPort
|
||||
},
|
||||
fs: {
|
||||
strict: false,
|
||||
allow: [
|
||||
nuxt.options.buildDir,
|
||||
nuxt.options.appDir,
|
||||
nuxt.options.srcDir,
|
||||
nuxt.options.rootDir,
|
||||
...nuxt.options.modulesDir
|
||||
nuxt.options.appDir
|
||||
]
|
||||
}
|
||||
}
|
||||
} as ViteOptions,
|
||||
nuxt.options.vite as any || {}
|
||||
},
|
||||
nuxt.options.vite
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -9,18 +9,14 @@ export default defineBuildConfig({
|
||||
'@nuxt/kit',
|
||||
'unplugin',
|
||||
'webpack-virtual-modules',
|
||||
'@vue/babel-preset-jsx',
|
||||
'postcss',
|
||||
'postcss-import-resolver',
|
||||
'postcss-loader',
|
||||
'babel-loader',
|
||||
'vue-loader',
|
||||
'css-loader',
|
||||
'file-loader',
|
||||
'style-resources-loader',
|
||||
'url-loader',
|
||||
'vue-style-loader',
|
||||
'@babel/core',
|
||||
'vue'
|
||||
],
|
||||
externals: [
|
||||
|
@ -19,9 +19,7 @@
|
||||
"@babel/core": "^7.17.5",
|
||||
"@nuxt/friendly-errors-webpack-plugin": "^2.5.2",
|
||||
"@nuxt/kit": "3.0.0",
|
||||
"@vue/babel-preset-jsx": "^1.2.4",
|
||||
"autoprefixer": "^10.4.2",
|
||||
"babel-loader": "^8.2.3",
|
||||
"css-loader": "^6.6.0",
|
||||
"css-minimizer-webpack-plugin": "^3.4.1",
|
||||
"cssnano": "^5.0.17",
|
||||
@ -29,7 +27,6 @@
|
||||
"escape-string-regexp": "^5.0.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"fs-extra": "^10.0.1",
|
||||
"glob": "^7.2.0",
|
||||
"hash-sum": "^2.0.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"memfs": "^3.4.1",
|
||||
@ -39,7 +36,6 @@
|
||||
"pify": "^5.0.0",
|
||||
"postcss": "^8.4.7",
|
||||
"postcss-import": "^14.0.2",
|
||||
"postcss-import-resolver": "^2.0.0",
|
||||
"postcss-loader": "^6.2.1",
|
||||
"postcss-url": "^10.1.3",
|
||||
"style-resources-loader": "^1.5.0",
|
||||
@ -59,7 +55,6 @@
|
||||
"devDependencies": {
|
||||
"@nuxt/schema": "3.0.0",
|
||||
"@types/pify": "^5.0.1",
|
||||
"@types/terser-webpack-plugin": "^5.0.4",
|
||||
"@types/webpack-bundle-analyzer": "^4.4.1",
|
||||
"@types/webpack-dev-middleware": "^5.0.2",
|
||||
"@types/webpack-hot-middleware": "^2.25.6",
|
||||
|
@ -3,7 +3,6 @@ import { resolve } from 'pathe'
|
||||
import webpack from 'webpack'
|
||||
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
|
||||
|
||||
import type { ClientOptions } from 'webpack-hot-middleware'
|
||||
import { joinURL } from 'ufo'
|
||||
import { applyPresets, WebpackConfigContext } from '../utils/config'
|
||||
import { nuxt } from '../presets/nuxt'
|
||||
@ -50,7 +49,7 @@ function clientHMR (ctx: WebpackConfigContext) {
|
||||
return
|
||||
}
|
||||
|
||||
const clientOptions = options.build.hotMiddleware?.client || {} as ClientOptions
|
||||
const clientOptions = options.webpack.hotMiddleware?.client || {}
|
||||
const hotMiddlewareClientOptions = {
|
||||
reload: true,
|
||||
timeout: 30000,
|
||||
@ -81,7 +80,7 @@ function clientPlugins (ctx: WebpackConfigContext) {
|
||||
|
||||
// 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')
|
||||
|
||||
// @ts-ignore
|
||||
@ -92,7 +91,7 @@ function clientPlugins (ctx: WebpackConfigContext) {
|
||||
openAnalyzer: !options.build.quiet,
|
||||
reportFilename: resolve(statsDir, `${ctx.name}.html`),
|
||||
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
|
||||
|
||||
// Server polyfills
|
||||
if (options.build.serverURLPolyfill) {
|
||||
if (options.webpack.serverURLPolyfill) {
|
||||
config.plugins.push(new webpack.ProvidePlugin({
|
||||
URL: [options.build.serverURLPolyfill, 'URL'],
|
||||
URLSearchParams: [options.build.serverURLPolyfill, 'URLSearchParams']
|
||||
URL: [options.webpack.serverURLPolyfill, 'URL'],
|
||||
URLSearchParams: [options.webpack.serverURLPolyfill, 'URLSearchParams']
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,15 @@
|
||||
import type { WebpackError } from 'webpack'
|
||||
export default class WarningIgnorePlugin {
|
||||
filter: (warn: WebpackError) => boolean
|
||||
import type { Compiler, WebpackError } from 'webpack'
|
||||
|
||||
constructor (filter) {
|
||||
export type WarningFilter = (warn: WebpackError) => boolean
|
||||
|
||||
export default class WarningIgnorePlugin {
|
||||
filter: WarningFilter
|
||||
|
||||
constructor (filter: WarningFilter) {
|
||||
this.filter = filter
|
||||
}
|
||||
|
||||
apply (compiler) /* istanbul ignore next */ {
|
||||
apply (compiler: Compiler) {
|
||||
compiler.hooks.done.tap('warnfix-plugin', (stats) => {
|
||||
stats.compilation.warnings = stats.compilation.warnings.filter(this.filter)
|
||||
})
|
||||
|
@ -1,15 +1,13 @@
|
||||
import { fileName, WebpackConfigContext } from '../utils/config'
|
||||
|
||||
export function assets (ctx: WebpackConfigContext) {
|
||||
const { options } = ctx
|
||||
|
||||
ctx.config.module.rules.push(
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg|webp)$/i,
|
||||
use: [{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
...options.build.loaders.imgUrl,
|
||||
...ctx.options.webpack.loaders.imgUrl,
|
||||
name: fileName(ctx, 'img')
|
||||
}
|
||||
}]
|
||||
@ -19,7 +17,7 @@ export function assets (ctx: WebpackConfigContext) {
|
||||
use: [{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
...options.build.loaders.fontUrl,
|
||||
...ctx.options.webpack.loaders.fontUrl,
|
||||
name: fileName(ctx, 'font')
|
||||
}
|
||||
}]
|
||||
@ -29,7 +27,7 @@ export function assets (ctx: WebpackConfigContext) {
|
||||
use: [{
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
...options.build.loaders.file,
|
||||
...ctx.options.webpack.loaders.file,
|
||||
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 escapeRegExp from 'escape-string-regexp'
|
||||
import { joinURL } from 'ufo'
|
||||
import WarningIgnorePlugin from '../plugins/warning-ignore'
|
||||
import WarningIgnorePlugin, { WarningFilter } from '../plugins/warning-ignore'
|
||||
import { WebpackConfigContext, applyPresets, fileName } from '../utils/config'
|
||||
|
||||
export function base (ctx: WebpackConfigContext) {
|
||||
@ -28,7 +28,7 @@ function baseConfig (ctx: WebpackConfigContext) {
|
||||
plugins: [],
|
||||
externals: [],
|
||||
optimization: {
|
||||
...options.build.optimization as any,
|
||||
...options.webpack.optimization,
|
||||
minimizer: []
|
||||
},
|
||||
experiments: {},
|
||||
@ -43,13 +43,13 @@ function baseConfig (ctx: WebpackConfigContext) {
|
||||
function basePlugins (ctx: WebpackConfigContext) {
|
||||
const { config, options, nuxt } = ctx
|
||||
|
||||
// Add timefix-plugin before others plugins
|
||||
// Add timefix-plugin before other plugins
|
||||
if (options.dev) {
|
||||
config.plugins.push(new TimeFixPlugin())
|
||||
}
|
||||
|
||||
// User plugins
|
||||
config.plugins.push(...(options.build.plugins || []))
|
||||
config.plugins.push(...(options.webpack.plugins || []))
|
||||
|
||||
// Ignore empty warnings
|
||||
config.plugins.push(new WarningIgnorePlugin(getWarningIgnoreFilter(ctx)))
|
||||
@ -60,7 +60,7 @@ function basePlugins (ctx: WebpackConfigContext) {
|
||||
// Friendly errors
|
||||
if (
|
||||
ctx.isServer ||
|
||||
(ctx.isDev && !options.build.quiet && options.build.friendlyErrors)
|
||||
(ctx.isDev && !options.build.quiet && options.webpack.friendlyErrors)
|
||||
) {
|
||||
ctx.config.plugins.push(
|
||||
new FriendlyErrorsWebpackPlugin({
|
||||
@ -71,6 +71,7 @@ function basePlugins (ctx: WebpackConfigContext) {
|
||||
)
|
||||
}
|
||||
|
||||
if (nuxt.options.webpack.profile) {
|
||||
// Webpackbar
|
||||
const colors = {
|
||||
client: 'green',
|
||||
@ -104,6 +105,7 @@ function basePlugins (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 filters = [
|
||||
const filters: WarningFilter[] = [
|
||||
// Hide warnings about plugins without a default export (#1179)
|
||||
warn => warn.name === 'ModuleDependencyWarning' &&
|
||||
warn.message.includes('export \'default\'') &&
|
||||
warn.message.includes('nuxt_plugin_'),
|
||||
...(options.build.warningIgnoreFilters || [])
|
||||
...(options.webpack.warningIgnoreFilters || [])
|
||||
]
|
||||
|
||||
return warn => !filters.some(ignoreFilter => ignoreFilter(warn))
|
||||
@ -224,11 +226,10 @@ function getEnv (ctx: WebpackConfigContext) {
|
||||
'process.env.VUE_ENV': JSON.stringify(ctx.name),
|
||||
'process.browser': ctx.isClient,
|
||||
'process.client': ctx.isClient,
|
||||
'process.server': ctx.isServer,
|
||||
'process.modern': ctx.isModern
|
||||
'process.server': ctx.isServer
|
||||
}
|
||||
|
||||
if (options.build.aggressiveCodeRemoval) {
|
||||
if (options.webpack.aggressiveCodeRemoval) {
|
||||
_env['typeof process'] = 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,
|
||||
loader: 'esbuild-loader',
|
||||
exclude: (file) => {
|
||||
file = file.split('node_modules', 2)[1]
|
||||
|
||||
// Not exclude files outside node_modules
|
||||
if (!file) {
|
||||
return false
|
||||
}
|
||||
file = file.split('node_modules', 2)[1]
|
||||
if (!file) { return false }
|
||||
|
||||
// Item in transpile can be string or regex object
|
||||
return !ctx.transpile.some(module => module.test(file))
|
||||
},
|
||||
resolve: {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { WebpackConfigContext } from '../utils/config'
|
||||
import type { WebpackConfigContext } from '../utils/config'
|
||||
|
||||
export function node (ctx: WebpackConfigContext) {
|
||||
const { config } = ctx
|
||||
|
@ -11,7 +11,6 @@ export function nuxt (ctx: WebpackConfigContext) {
|
||||
applyPresets(ctx, [
|
||||
base,
|
||||
assets,
|
||||
// babel,
|
||||
esbuild,
|
||||
pug,
|
||||
style,
|
||||
|
@ -8,7 +8,7 @@ export function pug (ctx: WebpackConfigContext) {
|
||||
resourceQuery: /^\?vue/i,
|
||||
use: [{
|
||||
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',
|
||||
{
|
||||
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 CssMinimizerPlugin from 'css-minimizer-webpack-plugin'
|
||||
import { fileName, WebpackConfigContext, applyPresets } from '../utils/config'
|
||||
import { PostcssConfig } from '../utils/postcss'
|
||||
import { getPostcssConfig } from '../utils/postcss'
|
||||
|
||||
export function style (ctx: WebpackConfigContext) {
|
||||
applyPresets(ctx, [
|
||||
@ -15,9 +14,9 @@ export function style (ctx: WebpackConfigContext) {
|
||||
function minimizer (ctx: WebpackConfigContext) {
|
||||
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({
|
||||
...options.build.optimizeCSS as any
|
||||
...options.webpack.optimizeCSS
|
||||
}))
|
||||
}
|
||||
}
|
||||
@ -26,11 +25,11 @@ function extractCSS (ctx: WebpackConfigContext) {
|
||||
const { options, config } = ctx
|
||||
|
||||
// CSS extraction
|
||||
if (options.build.extractCSS) {
|
||||
if (options.webpack.extractCSS) {
|
||||
config.plugins.push(new MiniCssExtractPlugin({
|
||||
filename: 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))
|
||||
|
||||
// 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))
|
||||
|
||||
// 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))
|
||||
|
||||
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))
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
@ -65,16 +64,15 @@ function createdStyleRule (lang: string, test: RegExp, processorLoader, ctx: Web
|
||||
|
||||
const styleLoaders = [
|
||||
createPostcssLoadersRule(ctx),
|
||||
processorLoader,
|
||||
createStyleResourcesLoaderRule(lang, options.build.styleResources, options.rootDir)
|
||||
processorLoader
|
||||
].filter(Boolean)
|
||||
|
||||
options.build.loaders.css.importLoaders =
|
||||
options.build.loaders.cssModules.importLoaders =
|
||||
options.webpack.loaders.css.importLoaders =
|
||||
options.webpack.loaders.cssModules.importLoaders =
|
||||
styleLoaders.length
|
||||
|
||||
const cssLoaders = createCssLoadersRule(ctx, options.build.loaders.css)
|
||||
const cssModuleLoaders = createCssLoadersRule(ctx, options.build.loaders.cssModules)
|
||||
const cssLoaders = createCssLoadersRule(ctx, options.webpack.loaders.css)
|
||||
const cssModuleLoaders = createCssLoadersRule(ctx, options.webpack.loaders.cssModules)
|
||||
|
||||
return {
|
||||
test,
|
||||
@ -97,7 +95,7 @@ function createCssLoadersRule (ctx: WebpackConfigContext, cssLoaderOptions) {
|
||||
|
||||
const cssLoader = { loader: 'css-loader', options: cssLoaderOptions }
|
||||
|
||||
if (options.build.extractCSS) {
|
||||
if (options.webpack.extractCSS) {
|
||||
if (ctx.isServer) {
|
||||
return [cssLoader]
|
||||
}
|
||||
@ -113,37 +111,18 @@ function createCssLoadersRule (ctx: WebpackConfigContext, cssLoaderOptions) {
|
||||
return [
|
||||
{
|
||||
loader: 'vue-style-loader',
|
||||
options: options.build.loaders.vueStyle
|
||||
options: options.webpack.loaders.vueStyle
|
||||
},
|
||||
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) {
|
||||
const { options, nuxt } = ctx
|
||||
|
||||
if (!options.build.postcss) {
|
||||
return
|
||||
}
|
||||
if (!options.postcss) { return }
|
||||
|
||||
const postcssConfig = new PostcssConfig(nuxt)
|
||||
const config = postcssConfig.config()
|
||||
const config = getPostcssConfig(nuxt)
|
||||
|
||||
if (!config) {
|
||||
return
|
||||
|
@ -14,7 +14,7 @@ export function vue (ctx: WebpackConfigContext) {
|
||||
config.module.rules.push({
|
||||
test: /\.vue$/i,
|
||||
loader: 'vue-loader',
|
||||
options: options.build.loaders.vue
|
||||
options: options.webpack.loaders.vue
|
||||
})
|
||||
|
||||
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 WebpackConfigPresetItem = WebpackConfigPreset | [WebpackConfigPreset, any]
|
||||
|
||||
export function createWebpackConfigContext ({ nuxt }) {
|
||||
export function createWebpackConfigContext (nuxt: Nuxt) {
|
||||
return {
|
||||
nuxt: nuxt as Nuxt,
|
||||
options: nuxt.options as Nuxt['options'],
|
||||
nuxt,
|
||||
options: nuxt.options,
|
||||
config: {} as Configuration,
|
||||
|
||||
name: 'base',
|
||||
isDev: nuxt.options.dev,
|
||||
isServer: false,
|
||||
isClient: false,
|
||||
isModern: undefined, // TODO
|
||||
isLegacy: false,
|
||||
|
||||
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) {
|
||||
const { options } = ctx
|
||||
|
||||
let fileName = options.build.filenames[key]
|
||||
let fileName = options.webpack.filenames[key]
|
||||
|
||||
if (typeof fileName === 'function') {
|
||||
fileName = fileName(ctx)
|
||||
|
@ -9,7 +9,7 @@ export function createMFS () {
|
||||
const fs = createFsFromVolume(new Volume())
|
||||
|
||||
// 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
|
||||
// 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.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 { defaults, merge, cloneDeep } from 'lodash-es'
|
||||
import createResolver from 'postcss-import-resolver'
|
||||
import { requireModule } from '@nuxt/kit'
|
||||
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 = {
|
||||
cssnanoLast (names) {
|
||||
cssnanoLast (names: string[]) {
|
||||
const nanoIndex = names.indexOf('cssnano')
|
||||
if (nanoIndex !== names.length - 1) {
|
||||
names.push(names.splice(nanoIndex, 1)[0])
|
||||
}
|
||||
return names
|
||||
},
|
||||
autoprefixerLast (names) {
|
||||
autoprefixerLast (names: string[]) {
|
||||
const nanoIndex = names.indexOf('autoprefixer')
|
||||
if (nanoIndex !== names.length - 1) {
|
||||
names.push(names.splice(nanoIndex, 1)[0])
|
||||
}
|
||||
return names
|
||||
},
|
||||
autoprefixerAndCssnanoLast (names) {
|
||||
autoprefixerAndCssnanoLast (names: string[]) {
|
||||
return orderPresets.cssnanoLast(orderPresets.autoprefixerLast(names))
|
||||
}
|
||||
}
|
||||
|
||||
let _postcssConfigFileWarningShown
|
||||
function postcssConfigFileWarning () {
|
||||
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
|
||||
export const getPostcssConfig = (nuxt: Nuxt) => {
|
||||
function defaultConfig () {
|
||||
return {
|
||||
sourceMap: this.options.build.cssSourceMap,
|
||||
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 }
|
||||
}]
|
||||
}
|
||||
},
|
||||
sourceMap: nuxt.options.webpack.cssSourceMap,
|
||||
plugins: nuxt.options.postcss.plugins,
|
||||
// Array, String or Function
|
||||
order: 'autoprefixerAndCssnanoLast'
|
||||
}
|
||||
}
|
||||
|
||||
searchConfigFile () {
|
||||
// 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 }) {
|
||||
function sortPlugins ({ plugins, order }) {
|
||||
const names = Object.keys(plugins)
|
||||
if (typeof order === 'string') {
|
||||
order = orderPresets[order]
|
||||
@ -138,11 +43,12 @@ export class PostcssConfig {
|
||||
return typeof order === 'function' ? order(names, orderPresets) : (order || names)
|
||||
}
|
||||
|
||||
loadPlugins (config) {
|
||||
function loadPlugins (config) {
|
||||
if (!isPureObject(config.plugins)) { return }
|
||||
|
||||
// Map postcss plugins into instances on object mode once
|
||||
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 pluginOptions = config.plugins[pluginName]
|
||||
if (!pluginOptions || typeof pluginFn !== 'function') { return null }
|
||||
@ -150,41 +56,37 @@ export class PostcssConfig {
|
||||
}).filter(Boolean)
|
||||
}
|
||||
|
||||
config () {
|
||||
/* istanbul ignore if */
|
||||
if (!this.options.build.postcss) {
|
||||
if (!nuxt.options.webpack.postcss || !nuxt.options.postcss) {
|
||||
return false
|
||||
}
|
||||
|
||||
const configFile = this.getConfigFile()
|
||||
const configFile = nuxt.options.postcss?.config
|
||||
if (configFile) {
|
||||
return {
|
||||
postcssOptions: {
|
||||
config: configFile
|
||||
},
|
||||
sourceMap: this.options.build.cssSourceMap
|
||||
sourceMap: nuxt.options.webpack.cssSourceMap
|
||||
}
|
||||
}
|
||||
|
||||
let postcssOptions = cloneDeep(this.postcssOptions)
|
||||
|
||||
let postcssOptions = cloneDeep(nuxt.options.postcss)
|
||||
// Apply default plugins
|
||||
if (isPureObject(postcssOptions)) {
|
||||
if (Array.isArray(postcssOptions.plugins)) {
|
||||
defaults(postcssOptions, this.defaultConfig)
|
||||
defaults(postcssOptions, defaultConfig())
|
||||
} else {
|
||||
// Keep the order of default plugins
|
||||
postcssOptions = merge({}, this.defaultConfig, postcssOptions)
|
||||
this.loadPlugins(postcssOptions)
|
||||
postcssOptions = merge({}, defaultConfig(), postcssOptions)
|
||||
loadPlugins(postcssOptions)
|
||||
}
|
||||
|
||||
delete this.options.build.postcss.order
|
||||
delete nuxt.options.webpack.postcss.order
|
||||
|
||||
return {
|
||||
sourceMap: this.options.build.cssSourceMap,
|
||||
...this.options.build.postcss,
|
||||
sourceMap: nuxt.options.webpack.cssSourceMap,
|
||||
...nuxt.options.webpack.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,122 +1,41 @@
|
||||
import type { IncomingMessage, ServerResponse } from 'http'
|
||||
import { resolve } from 'pathe'
|
||||
import pify from 'pify'
|
||||
import webpack from 'webpack'
|
||||
import Glob from 'glob'
|
||||
import webpackDevMiddleware from 'webpack-dev-middleware'
|
||||
import webpackDevMiddleware, { API } from 'webpack-dev-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 { 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 { joinURL } from 'ufo'
|
||||
import { logger, useNuxt } from '@nuxt/kit'
|
||||
import { DynamicBasePlugin } from '../../vite/src/plugins/dynamic-base'
|
||||
import { createMFS } from './utils/mfs'
|
||||
import { registerVirtualModules } from './virtual-modules'
|
||||
import { client, server } from './configs'
|
||||
import { createWebpackConfigContext, applyPresets, getWebpackConfig } from './utils/config'
|
||||
|
||||
const glob = pify(Glob)
|
||||
class WebpackBundler {
|
||||
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
|
||||
// TODO: Support plugins
|
||||
// const plugins: string[] = []
|
||||
|
||||
constructor (nuxt: Nuxt) {
|
||||
this.nuxt = nuxt
|
||||
// TODO: plugins
|
||||
this.plugins = []
|
||||
export async function bundle (nuxt: Nuxt) {
|
||||
await registerVirtualModules()
|
||||
|
||||
// Class fields
|
||||
this.compilers = []
|
||||
this.compilersWatching = []
|
||||
this.devMiddleware = {}
|
||||
this.hotMiddleware = {}
|
||||
const webpackConfigs = [client, ...nuxt.options.ssr ? [server] : []].map((preset) => {
|
||||
const ctx = createWebpackConfigContext(nuxt)
|
||||
applyPresets(ctx, preset)
|
||||
return getWebpackConfig(ctx)
|
||||
})
|
||||
|
||||
// Bind middleware to self
|
||||
this.middleware = this.middleware.bind(this)
|
||||
await nuxt.callHook('webpack:config', webpackConfigs)
|
||||
|
||||
// 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}`)
|
||||
}
|
||||
|
||||
return getWebpackConfig(ctx)
|
||||
}
|
||||
|
||||
async build () {
|
||||
const { options } = this.nuxt
|
||||
|
||||
const webpackConfigs = [
|
||||
this.getWebpackConfig('client')
|
||||
]
|
||||
|
||||
if (options.ssr) {
|
||||
webpackConfigs.push(this.getWebpackConfig('server'))
|
||||
}
|
||||
|
||||
await this.nuxt.callHook('webpack:config', webpackConfigs)
|
||||
|
||||
// Check styleResource existence
|
||||
const { styleResources } = this.nuxt.options.build
|
||||
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}`)
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
const mfs = nuxt.options.dev ? createMFS() : null
|
||||
|
||||
// Configure compilers
|
||||
this.compilers = webpackConfigs.map((config) => {
|
||||
// Support virtual modules (input)
|
||||
config.plugins.push(this.virtualModules)
|
||||
const compilers = webpackConfigs.map((config) => {
|
||||
config.plugins.push(DynamicBasePlugin.webpack({
|
||||
env: this.nuxt.options.dev ? 'dev' : config.name as 'client',
|
||||
devAppConfig: this.nuxt.options.app,
|
||||
env: nuxt.options.dev ? 'dev' : config.name as 'client',
|
||||
devAppConfig: nuxt.options.app,
|
||||
globalPublicPath: '__webpack_public_path__'
|
||||
}))
|
||||
|
||||
@ -124,179 +43,120 @@ class WebpackBundler {
|
||||
const compiler = webpack(config)
|
||||
|
||||
// In dev, write files in memory FS
|
||||
if (options.dev) {
|
||||
compiler.outputFileSystem = this.mfs!
|
||||
if (nuxt.options.dev) {
|
||||
compiler.outputFileSystem = mfs
|
||||
}
|
||||
|
||||
return compiler
|
||||
})
|
||||
|
||||
nuxt.hook('close', async () => {
|
||||
for (const compiler of compilers) {
|
||||
await new Promise(resolve => compiler.close(resolve))
|
||||
}
|
||||
})
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
if (nuxt.options.dev) {
|
||||
return Promise.all(compilers.map(c => compile(c)))
|
||||
}
|
||||
|
||||
async webpackCompile (compiler) {
|
||||
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
|
||||
const { options } = this.nuxt
|
||||
|
||||
await this.nuxt.callHook('build:compile', { name, compiler })
|
||||
await 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
|
||||
})
|
||||
|
||||
await nuxt.callHook('build:compiled', { name, compiler, stats })
|
||||
// Reload renderer
|
||||
await this.nuxt.callHook('build:resources', this.mfs)
|
||||
await nuxt.callHook('build:resources', compiler.outputFileSystem)
|
||||
})
|
||||
|
||||
// --- Dev Build ---
|
||||
if (options.dev) {
|
||||
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 (['client', 'modern'].includes(name)) {
|
||||
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
|
||||
this.webpackDev(compiler)
|
||||
createDevMiddleware(compiler).then((devMiddleware) => {
|
||||
compilersWatching.push(devMiddleware.context.watching)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Server, build and watch for changes
|
||||
return new Promise((resolve, reject) => {
|
||||
const watching = compiler.watch(options.watchers.webpack, (err) => {
|
||||
if (err) {
|
||||
return reject(err)
|
||||
}
|
||||
const watching = compiler.watch(nuxt.options.watchers.webpack, (err) => {
|
||||
if (err) { return reject(err) }
|
||||
resolve(null)
|
||||
})
|
||||
|
||||
watching.closeAsync = pify(watching.close)
|
||||
this.compilersWatching.push(watching)
|
||||
compilersWatching.push(watching)
|
||||
})
|
||||
}
|
||||
|
||||
// --- Production Build ---
|
||||
compiler.run = pify(compiler.run)
|
||||
const stats = await compiler.run()
|
||||
const stats = await new Promise<webpack.Stats>((resolve, reject) => compiler.run((err, stats) => err ? reject(err) : resolve(stats)))
|
||||
|
||||
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) {
|
||||
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 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))
|
||||
}
|
||||
|
||||
// Cleanup MFS
|
||||
if (this.mfs) {
|
||||
delete this.mfs
|
||||
}
|
||||
|
||||
// Cleanup more resources
|
||||
delete this.compilers
|
||||
delete this.compilersWatching
|
||||
delete this.devMiddleware
|
||||
delete this.hotMiddleware
|
||||
}
|
||||
|
||||
forGenerate () {
|
||||
this.nuxt.options.target = 'static'
|
||||
}
|
||||
}
|
||||
|
||||
export function bundle (nuxt: Nuxt) {
|
||||
const bundler = new WebpackBundler(nuxt)
|
||||
return bundler.build()
|
||||
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({
|
||||
buildDir: process.env.NITRO_BUILD_DIR,
|
||||
vite: !process.env.TEST_WITH_WEBPACK,
|
||||
builder: process.env.TEST_WITH_WEBPACK ? 'webpack' : 'vite',
|
||||
nitro: {
|
||||
output: { dir: process.env.NITRO_OUTPUT_DIR }
|
||||
},
|
||||
|
61
yarn.lock
61
yarn.lock
@ -3163,6 +3163,7 @@ __metadata:
|
||||
defu: ^5.0.1
|
||||
jiti: ^1.13.0
|
||||
pathe: ^0.2.0
|
||||
postcss-import-resolver: ^2.0.0
|
||||
scule: ^0.2.1
|
||||
std-env: ^3.0.1
|
||||
ufo: ^0.7.9
|
||||
@ -3393,7 +3394,6 @@ __metadata:
|
||||
p-debounce: ^4.0.0
|
||||
pathe: ^0.2.0
|
||||
postcss-import: ^14.0.2
|
||||
postcss-import-resolver: ^2.0.0
|
||||
postcss-url: ^10.1.3
|
||||
rollup-plugin-visualizer: ^5.6.0
|
||||
ufo: ^0.7.9
|
||||
@ -3480,7 +3480,7 @@ __metadata:
|
||||
languageName: node
|
||||
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
|
||||
resolution: "@nuxt/webpack-builder@workspace:packages/webpack"
|
||||
dependencies:
|
||||
@ -3489,14 +3489,11 @@ __metadata:
|
||||
"@nuxt/kit": 3.0.0
|
||||
"@nuxt/schema": 3.0.0
|
||||
"@types/pify": ^5.0.1
|
||||
"@types/terser-webpack-plugin": ^5.0.4
|
||||
"@types/webpack-bundle-analyzer": ^4.4.1
|
||||
"@types/webpack-dev-middleware": ^5.0.2
|
||||
"@types/webpack-hot-middleware": ^2.25.6
|
||||
"@types/webpack-virtual-modules": ^0
|
||||
"@vue/babel-preset-jsx": ^1.2.4
|
||||
autoprefixer: ^10.4.2
|
||||
babel-loader: ^8.2.3
|
||||
css-loader: ^6.6.0
|
||||
css-minimizer-webpack-plugin: ^3.4.1
|
||||
cssnano: ^5.0.17
|
||||
@ -3504,7 +3501,6 @@ __metadata:
|
||||
escape-string-regexp: ^5.0.0
|
||||
file-loader: ^6.2.0
|
||||
fs-extra: ^10.0.1
|
||||
glob: ^7.2.0
|
||||
hash-sum: ^2.0.0
|
||||
lodash-es: ^4.17.21
|
||||
memfs: ^3.4.1
|
||||
@ -3514,7 +3510,6 @@ __metadata:
|
||||
pify: ^5.0.0
|
||||
postcss: ^8.4.7
|
||||
postcss-import: ^14.0.2
|
||||
postcss-import-resolver: ^2.0.0
|
||||
postcss-loader: ^6.2.1
|
||||
postcss-url: ^10.1.3
|
||||
style-resources-loader: ^1.5.0
|
||||
@ -4630,16 +4625,6 @@ __metadata:
|
||||
languageName: node
|
||||
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":
|
||||
version: 2.1.0
|
||||
resolution: "@types/throttle-debounce@npm:2.1.0"
|
||||
@ -15675,7 +15660,6 @@ __metadata:
|
||||
"@nuxt/nitro": 3.0.0
|
||||
"@nuxt/schema": 3.0.0
|
||||
"@nuxt/vite-builder": 3.0.0
|
||||
"@nuxt/webpack-builder": 3.0.0
|
||||
"@types/fs-extra": ^9.0.13
|
||||
"@types/hash-sum": ^1.0.0
|
||||
"@vue/reactivity": ^3.2.31
|
||||
@ -20771,7 +20755,7 @@ __metadata:
|
||||
languageName: node
|
||||
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
|
||||
resolution: "terser@npm:5.10.0"
|
||||
dependencies:
|
||||
@ -22553,44 +22537,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"webpack@npm:^5, webpack@npm:^5.1.0, webpack@npm:^5.38.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":
|
||||
"webpack@npm:^5, webpack@npm:^5.38.1, webpack@npm:^5.69.1":
|
||||
version: 5.69.1
|
||||
resolution: "webpack@npm:5.69.1"
|
||||
dependencies:
|
||||
|
Loading…
Reference in New Issue
Block a user