@nuxt/webpack-builder 0.10.0 → 3.0.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1 +1,5 @@
1
- This is a placeholder package. Please use [@nuxt/webpack-builder-edge](https://www.npmjs.com/package/@nuxt/webpack-builder-edge). Learn more: https://v3.nuxtjs.org
1
+ # Nuxt Webpack Builder
2
+
3
+ > The [Webpack](https://webpack.js.org) bundler for Nuxt 3
4
+
5
+ Learn more about this package: <https://v3.nuxtjs.org>
@@ -0,0 +1,5 @@
1
+ import { Nuxt } from '@nuxt/schema';
2
+
3
+ declare function bundle(nuxt: Nuxt): Promise<unknown[]>;
4
+
5
+ export { bundle };
package/dist/index.mjs ADDED
@@ -0,0 +1,1050 @@
1
+ import pify from 'pify';
2
+ import webpack from 'webpack';
3
+ import webpackDevMiddleware from 'webpack-dev-middleware';
4
+ import webpackHotMiddleware from 'webpack-hot-middleware';
5
+ import { joinURL } from 'ufo';
6
+ import { useNuxt, logger, requireModule } from '@nuxt/kit';
7
+ import { createUnplugin } from 'unplugin';
8
+ import 'escape-string-regexp';
9
+ import MagicString from 'magic-string';
10
+ import { join, resolve, dirname, isAbsolute } from 'pathe';
11
+ import { createFsFromVolume, Volume } from 'memfs';
12
+ import VirtualModulesPlugin from 'webpack-virtual-modules';
13
+ import querystring from 'node:querystring';
14
+ import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
15
+ import { cloneDeep, defaults, merge, uniq } from 'lodash-es';
16
+ import TimeFixPlugin from 'time-fix-plugin';
17
+ import WebpackBar from 'webpackbar';
18
+ import FriendlyErrorsWebpackPlugin from '@nuxt/friendly-errors-webpack-plugin';
19
+ import esbuildLoader from 'esbuild-loader';
20
+ import MiniCssExtractPlugin from 'mini-css-extract-plugin';
21
+ import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
22
+ import { createCommonJS } from 'mlly';
23
+ import VueLoaderPlugin from 'vue-loader/dist/pluginWebpack5.js';
24
+ import hash from 'hash-sum';
25
+ import fse from 'fs-extra';
26
+ import ForkTSCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
27
+
28
+ const VITE_ASSET_RE = /^export default ["'](__VITE_ASSET.*)["']$/;
29
+ const DynamicBasePlugin = createUnplugin(function(options = {}) {
30
+ return {
31
+ name: "nuxt:dynamic-base-path",
32
+ resolveId(id) {
33
+ if (id.startsWith("/__NUXT_BASE__")) {
34
+ return id.replace("/__NUXT_BASE__", "");
35
+ }
36
+ if (id === "#internal/nitro") {
37
+ return "#internal/nitro";
38
+ }
39
+ return null;
40
+ },
41
+ enforce: "post",
42
+ transform(code, id) {
43
+ const s = new MagicString(code);
44
+ if (options.globalPublicPath && id.includes("paths.mjs") && code.includes("const appConfig = ")) {
45
+ s.append(`${options.globalPublicPath} = buildAssetsURL();
46
+ `);
47
+ }
48
+ const assetId = code.match(VITE_ASSET_RE);
49
+ if (assetId) {
50
+ s.overwrite(0, code.length, [
51
+ "import { buildAssetsURL } from '#build/paths.mjs';",
52
+ `export default buildAssetsURL("${assetId[1]}".replace("/__NUXT_BASE__", ""));`
53
+ ].join("\n"));
54
+ }
55
+ if (!id.includes("paths.mjs") && code.includes("NUXT_BASE") && !code.includes("import { publicAssetsURL as __publicAssetsURL }")) {
56
+ s.prepend("import { publicAssetsURL as __publicAssetsURL } from '#build/paths.mjs';\n");
57
+ }
58
+ if (id === "vite/preload-helper") {
59
+ s.prepend("import { buildAssetsDir } from '#build/paths.mjs';\n");
60
+ s.replace(/const base = ['"]\/__NUXT_BASE__\/['"]/, "const base = buildAssetsDir()");
61
+ }
62
+ s.replace(/from *['"]\/__NUXT_BASE__(\/[^'"]*)['"]/g, 'from "$1"');
63
+ const delimiterRE = /(?<!(const base = |from *))(`([^`]*)\/__NUXT_BASE__\/([^`]*)`|'([^\n']*)\/__NUXT_BASE__\/([^\n']*)'|"([^\n"]*)\/__NUXT_BASE__\/([^\n"]*)")/g;
64
+ s.replace(delimiterRE, (r) => "`" + r.replace(/\/__NUXT_BASE__\//g, "${__publicAssetsURL()}").slice(1, -1) + "`");
65
+ if (s.hasChanged()) {
66
+ return {
67
+ code: s.toString(),
68
+ map: options.sourcemap && s.generateMap({ source: id, includeContent: true })
69
+ };
70
+ }
71
+ }
72
+ };
73
+ });
74
+
75
+ function createMFS() {
76
+ const fs = createFsFromVolume(new Volume());
77
+ const _fs = { ...fs };
78
+ _fs.join = join;
79
+ _fs.exists = (p) => Promise.resolve(_fs.existsSync(p));
80
+ _fs.readFile = pify(_fs.readFile);
81
+ return _fs;
82
+ }
83
+
84
+ function registerVirtualModules() {
85
+ const nuxt = useNuxt();
86
+ const virtualModules = new VirtualModulesPlugin(nuxt.vfs);
87
+ const writeFiles = () => {
88
+ for (const filePath in nuxt.vfs) {
89
+ virtualModules.writeModule(filePath, nuxt.vfs[filePath]);
90
+ }
91
+ };
92
+ nuxt.hook("build:compile", ({ compiler }) => {
93
+ if (compiler.name === "server") {
94
+ writeFiles();
95
+ }
96
+ });
97
+ nuxt.hook("app:templatesGenerated", writeFiles);
98
+ nuxt.hook("webpack:config", (configs) => configs.forEach((config) => {
99
+ config.plugins.push(virtualModules);
100
+ }));
101
+ }
102
+
103
+ function createWebpackConfigContext(nuxt) {
104
+ return {
105
+ nuxt,
106
+ options: nuxt.options,
107
+ config: {},
108
+ name: "base",
109
+ isDev: nuxt.options.dev,
110
+ isServer: false,
111
+ isClient: false,
112
+ alias: {},
113
+ transpile: []
114
+ };
115
+ }
116
+ function applyPresets(ctx, presets) {
117
+ if (!Array.isArray(presets)) {
118
+ presets = [presets];
119
+ }
120
+ for (const preset of presets) {
121
+ if (Array.isArray(preset)) {
122
+ preset[0](ctx, preset[1]);
123
+ } else {
124
+ preset(ctx);
125
+ }
126
+ }
127
+ }
128
+ function fileName(ctx, key) {
129
+ const { options } = ctx;
130
+ let fileName2 = options.webpack.filenames[key];
131
+ if (typeof fileName2 === "function") {
132
+ fileName2 = fileName2(ctx);
133
+ }
134
+ if (typeof fileName2 === "string" && options.dev) {
135
+ const hash = /\[(chunkhash|contenthash|hash)(?::(\d+))?]/.exec(fileName2);
136
+ if (hash) {
137
+ logger.warn(`Notice: Please do not use ${hash[1]} in dev mode to prevent memory leak`);
138
+ }
139
+ }
140
+ return fileName2;
141
+ }
142
+ function getWebpackConfig(ctx) {
143
+ const { options, config } = ctx;
144
+ const builder = {};
145
+ const loaders = [];
146
+ const { extend } = options.build;
147
+ if (typeof extend === "function") {
148
+ const extendedConfig = extend.call(builder, config, { loaders, ...ctx }) || config;
149
+ const pragma = /@|#/;
150
+ const { devtool } = extendedConfig;
151
+ if (typeof devtool === "string" && pragma.test(devtool)) {
152
+ extendedConfig.devtool = devtool.replace(pragma, "");
153
+ logger.warn(`devtool has been normalized to ${extendedConfig.devtool} as webpack documented value`);
154
+ }
155
+ return extendedConfig;
156
+ }
157
+ return cloneDeep(config);
158
+ }
159
+
160
+ function assets(ctx) {
161
+ ctx.config.module.rules.push({
162
+ test: /\.(png|jpe?g|gif|svg|webp)$/i,
163
+ use: [{
164
+ loader: "url-loader",
165
+ options: {
166
+ ...ctx.options.webpack.loaders.imgUrl,
167
+ name: fileName(ctx, "img")
168
+ }
169
+ }]
170
+ }, {
171
+ test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
172
+ use: [{
173
+ loader: "url-loader",
174
+ options: {
175
+ ...ctx.options.webpack.loaders.fontUrl,
176
+ name: fileName(ctx, "font")
177
+ }
178
+ }]
179
+ }, {
180
+ test: /\.(webm|mp4|ogv)$/i,
181
+ use: [{
182
+ loader: "file-loader",
183
+ options: {
184
+ ...ctx.options.webpack.loaders.file,
185
+ name: fileName(ctx, "video")
186
+ }
187
+ }]
188
+ });
189
+ }
190
+
191
+ class WarningIgnorePlugin {
192
+ constructor(filter) {
193
+ this.filter = filter;
194
+ }
195
+ apply(compiler) {
196
+ compiler.hooks.done.tap("warnfix-plugin", (stats) => {
197
+ stats.compilation.warnings = stats.compilation.warnings.filter(this.filter);
198
+ });
199
+ }
200
+ }
201
+
202
+ function base(ctx) {
203
+ applyPresets(ctx, [
204
+ baseAlias,
205
+ baseConfig,
206
+ basePlugins,
207
+ baseResolve
208
+ ]);
209
+ }
210
+ function baseConfig(ctx) {
211
+ const { options } = ctx;
212
+ ctx.config = {
213
+ name: ctx.name,
214
+ entry: { app: [resolve(options.appDir, options.experimental.asyncEntry ? "entry.async" : "entry")] },
215
+ module: { rules: [] },
216
+ plugins: [],
217
+ externals: [],
218
+ optimization: {
219
+ ...options.webpack.optimization,
220
+ minimizer: []
221
+ },
222
+ experiments: {},
223
+ mode: ctx.isDev ? "development" : "production",
224
+ cache: getCache(ctx),
225
+ output: getOutput(ctx),
226
+ stats: "none",
227
+ ...ctx.config
228
+ };
229
+ }
230
+ function basePlugins(ctx) {
231
+ const { config, options, nuxt } = ctx;
232
+ if (options.dev) {
233
+ config.plugins.push(new TimeFixPlugin());
234
+ }
235
+ config.plugins.push(...options.webpack.plugins || []);
236
+ config.plugins.push(new WarningIgnorePlugin(getWarningIgnoreFilter(ctx)));
237
+ config.plugins.push(new webpack.DefinePlugin(getEnv(ctx)));
238
+ if (ctx.isServer || ctx.isDev && !options.build.quiet && options.webpack.friendlyErrors) {
239
+ ctx.config.plugins.push(new FriendlyErrorsWebpackPlugin({
240
+ clearConsole: false,
241
+ reporter: "consola",
242
+ logLevel: "ERROR"
243
+ }));
244
+ }
245
+ if (nuxt.options.webpack.profile) {
246
+ const colors = {
247
+ client: "green",
248
+ server: "orange",
249
+ modern: "blue"
250
+ };
251
+ config.plugins.push(new WebpackBar({
252
+ name: ctx.name,
253
+ color: colors[ctx.name],
254
+ reporters: ["stats"],
255
+ stats: !ctx.isDev,
256
+ reporter: {
257
+ change: (_, { shortPath }) => {
258
+ if (!ctx.isServer) {
259
+ nuxt.callHook("bundler:change", shortPath);
260
+ }
261
+ },
262
+ done: ({ state }) => {
263
+ if (state.hasErrors) {
264
+ nuxt.callHook("bundler:error");
265
+ } else {
266
+ logger.success(`${state.name} ${state.message}`);
267
+ }
268
+ },
269
+ allDone: () => {
270
+ nuxt.callHook("bundler:done");
271
+ },
272
+ progress({ statesArray }) {
273
+ nuxt.callHook("bundler:progress", statesArray);
274
+ }
275
+ }
276
+ }));
277
+ }
278
+ }
279
+ function baseAlias(ctx) {
280
+ const { options } = ctx;
281
+ ctx.alias = {
282
+ "#app": options.appDir,
283
+ "#build/plugins": resolve(options.buildDir, "plugins", ctx.isClient ? "client" : "server"),
284
+ "#build": options.buildDir,
285
+ ...options.alias,
286
+ ...ctx.alias
287
+ };
288
+ if (ctx.isClient) {
289
+ ctx.alias["#internal/nitro"] = resolve(ctx.nuxt.options.buildDir, "nitro.client.mjs");
290
+ }
291
+ }
292
+ function baseResolve(ctx) {
293
+ const { options, config } = ctx;
294
+ const webpackModulesDir = ["node_modules"].concat(options.modulesDir);
295
+ config.resolve = {
296
+ extensions: [".wasm", ".mjs", ".js", ".ts", ".json", ".vue", ".jsx", ".tsx"],
297
+ alias: ctx.alias,
298
+ modules: webpackModulesDir,
299
+ fullySpecified: false,
300
+ ...config.resolve
301
+ };
302
+ config.resolveLoader = {
303
+ modules: webpackModulesDir,
304
+ ...config.resolveLoader
305
+ };
306
+ }
307
+ function getCache(ctx) {
308
+ const { options } = ctx;
309
+ if (!options.dev) {
310
+ return false;
311
+ }
312
+ }
313
+ function getOutput(ctx) {
314
+ const { options } = ctx;
315
+ return {
316
+ path: resolve(options.buildDir, "dist", ctx.isServer ? "server" : "client"),
317
+ filename: fileName(ctx, "app"),
318
+ chunkFilename: fileName(ctx, "chunk"),
319
+ publicPath: joinURL(options.app.baseURL, options.app.buildAssetsDir)
320
+ };
321
+ }
322
+ function getWarningIgnoreFilter(ctx) {
323
+ const { options } = ctx;
324
+ const filters = [
325
+ (warn) => warn.name === "ModuleDependencyWarning" && warn.message.includes("export 'default'") && warn.message.includes("nuxt_plugin_"),
326
+ ...options.webpack.warningIgnoreFilters || []
327
+ ];
328
+ return (warn) => !filters.some((ignoreFilter) => ignoreFilter(warn));
329
+ }
330
+ function getEnv(ctx) {
331
+ const { options } = ctx;
332
+ const _env = {
333
+ "process.env.NODE_ENV": JSON.stringify(ctx.config.mode),
334
+ "process.mode": JSON.stringify(ctx.config.mode),
335
+ "process.dev": options.dev,
336
+ "process.static": options.target === "static",
337
+ "process.target": JSON.stringify(options.target),
338
+ "process.env.VUE_ENV": JSON.stringify(ctx.name),
339
+ "process.browser": ctx.isClient,
340
+ "process.client": ctx.isClient,
341
+ "process.server": ctx.isServer
342
+ };
343
+ if (options.webpack.aggressiveCodeRemoval) {
344
+ _env["typeof process"] = JSON.stringify(ctx.isServer ? "object" : "undefined");
345
+ _env["typeof window"] = _env["typeof document"] = JSON.stringify(!ctx.isServer ? "object" : "undefined");
346
+ }
347
+ Object.entries(options.env).forEach(([key, value]) => {
348
+ const isNative = ["boolean", "number"].includes(typeof value);
349
+ _env["process.env." + key] = isNative ? value : JSON.stringify(value);
350
+ });
351
+ return _env;
352
+ }
353
+
354
+ function esbuild(ctx) {
355
+ const { config } = ctx;
356
+ const target = ctx.isServer ? "es2019" : "chrome85";
357
+ config.optimization.minimizer.push(new esbuildLoader.ESBuildMinifyPlugin());
358
+ config.module.rules.push({
359
+ test: /\.m?[jt]s$/i,
360
+ loader: "esbuild-loader",
361
+ exclude: (file) => {
362
+ file = file.split("node_modules", 2)[1];
363
+ if (!file) {
364
+ return false;
365
+ }
366
+ return !ctx.transpile.some((module) => module.test(file));
367
+ },
368
+ resolve: {
369
+ fullySpecified: false
370
+ },
371
+ options: {
372
+ loader: "ts",
373
+ target
374
+ }
375
+ }, {
376
+ test: /\.m?[jt]sx$/,
377
+ loader: "esbuild-loader",
378
+ options: {
379
+ loader: "tsx",
380
+ target
381
+ }
382
+ });
383
+ }
384
+
385
+ function pug(ctx) {
386
+ ctx.config.module.rules.push({
387
+ test: /\.pug$/i,
388
+ oneOf: [
389
+ {
390
+ resourceQuery: /^\?vue/i,
391
+ use: [{
392
+ loader: "pug-plain-loader",
393
+ options: ctx.options.webpack.loaders.pugPlain
394
+ }]
395
+ },
396
+ {
397
+ use: [
398
+ "raw-loader",
399
+ {
400
+ loader: "pug-plain-loader",
401
+ options: ctx.options.webpack.loaders.pugPlain
402
+ }
403
+ ]
404
+ }
405
+ ]
406
+ });
407
+ }
408
+
409
+ const isPureObject = (obj) => obj !== null && !Array.isArray(obj) && typeof obj === "object";
410
+ const orderPresets = {
411
+ cssnanoLast(names) {
412
+ const nanoIndex = names.indexOf("cssnano");
413
+ if (nanoIndex !== names.length - 1) {
414
+ names.push(names.splice(nanoIndex, 1)[0]);
415
+ }
416
+ return names;
417
+ },
418
+ autoprefixerLast(names) {
419
+ const nanoIndex = names.indexOf("autoprefixer");
420
+ if (nanoIndex !== names.length - 1) {
421
+ names.push(names.splice(nanoIndex, 1)[0]);
422
+ }
423
+ return names;
424
+ },
425
+ autoprefixerAndCssnanoLast(names) {
426
+ return orderPresets.cssnanoLast(orderPresets.autoprefixerLast(names));
427
+ }
428
+ };
429
+ const getPostcssConfig = (nuxt) => {
430
+ function defaultConfig() {
431
+ return {
432
+ sourceMap: nuxt.options.webpack.cssSourceMap,
433
+ plugins: nuxt.options.postcss.plugins,
434
+ order: "autoprefixerAndCssnanoLast"
435
+ };
436
+ }
437
+ function sortPlugins({ plugins, order }) {
438
+ const names = Object.keys(plugins);
439
+ if (typeof order === "string") {
440
+ order = orderPresets[order];
441
+ }
442
+ return typeof order === "function" ? order(names, orderPresets) : order || names;
443
+ }
444
+ function loadPlugins(config) {
445
+ if (!isPureObject(config.plugins)) {
446
+ return;
447
+ }
448
+ const cjs = createCommonJS(import.meta.url);
449
+ config.plugins = sortPlugins(config).map((pluginName) => {
450
+ const pluginFn = requireModule(pluginName, { paths: [cjs.__dirname] });
451
+ const pluginOptions = config.plugins[pluginName];
452
+ if (!pluginOptions || typeof pluginFn !== "function") {
453
+ return null;
454
+ }
455
+ return pluginFn(pluginOptions);
456
+ }).filter(Boolean);
457
+ }
458
+ if (!nuxt.options.webpack.postcss || !nuxt.options.postcss) {
459
+ return false;
460
+ }
461
+ const configFile = nuxt.options.postcss?.config;
462
+ if (configFile) {
463
+ return {
464
+ postcssOptions: {
465
+ config: configFile
466
+ },
467
+ sourceMap: nuxt.options.webpack.cssSourceMap
468
+ };
469
+ }
470
+ let postcssOptions = cloneDeep(nuxt.options.postcss);
471
+ if (isPureObject(postcssOptions)) {
472
+ if (Array.isArray(postcssOptions.plugins)) {
473
+ defaults(postcssOptions, defaultConfig());
474
+ } else {
475
+ postcssOptions = merge({}, defaultConfig(), postcssOptions);
476
+ loadPlugins(postcssOptions);
477
+ }
478
+ delete nuxt.options.webpack.postcss.order;
479
+ return {
480
+ sourceMap: nuxt.options.webpack.cssSourceMap,
481
+ ...nuxt.options.webpack.postcss,
482
+ postcssOptions
483
+ };
484
+ }
485
+ };
486
+
487
+ function style(ctx) {
488
+ applyPresets(ctx, [
489
+ loaders,
490
+ extractCSS,
491
+ minimizer
492
+ ]);
493
+ }
494
+ function minimizer(ctx) {
495
+ const { options, config } = ctx;
496
+ if (options.webpack.optimizeCSS && Array.isArray(config.optimization.minimizer)) {
497
+ config.optimization.minimizer.push(new CssMinimizerPlugin({
498
+ ...options.webpack.optimizeCSS
499
+ }));
500
+ }
501
+ }
502
+ function extractCSS(ctx) {
503
+ const { options, config } = ctx;
504
+ if (options.webpack.extractCSS) {
505
+ config.plugins.push(new MiniCssExtractPlugin({
506
+ filename: fileName(ctx, "css"),
507
+ chunkFilename: fileName(ctx, "css"),
508
+ ...options.webpack.extractCSS
509
+ }));
510
+ }
511
+ }
512
+ function loaders(ctx) {
513
+ const { config, options } = ctx;
514
+ config.module.rules.push(createdStyleRule("css", /\.css$/i, null, ctx));
515
+ config.module.rules.push(createdStyleRule("postcss", /\.p(ost)?css$/i, null, ctx));
516
+ const lessLoader = { loader: "less-loader", options: options.webpack.loaders.less };
517
+ config.module.rules.push(createdStyleRule("less", /\.less$/i, lessLoader, ctx));
518
+ const sassLoader = { loader: "sass-loader", options: options.webpack.loaders.sass };
519
+ config.module.rules.push(createdStyleRule("sass", /\.sass$/i, sassLoader, ctx));
520
+ const scssLoader = { loader: "sass-loader", options: options.webpack.loaders.scss };
521
+ config.module.rules.push(createdStyleRule("scss", /\.scss$/i, scssLoader, ctx));
522
+ const stylusLoader = { loader: "stylus-loader", options: options.webpack.loaders.stylus };
523
+ config.module.rules.push(createdStyleRule("stylus", /\.styl(us)?$/i, stylusLoader, ctx));
524
+ }
525
+ function createdStyleRule(lang, test, processorLoader, ctx) {
526
+ const { options } = ctx;
527
+ const styleLoaders = [
528
+ createPostcssLoadersRule(ctx),
529
+ processorLoader
530
+ ].filter(Boolean);
531
+ options.webpack.loaders.css.importLoaders = options.webpack.loaders.cssModules.importLoaders = styleLoaders.length;
532
+ const cssLoaders = createCssLoadersRule(ctx, options.webpack.loaders.css);
533
+ const cssModuleLoaders = createCssLoadersRule(ctx, options.webpack.loaders.cssModules);
534
+ return {
535
+ test,
536
+ oneOf: [
537
+ {
538
+ resourceQuery: /module/,
539
+ use: cssModuleLoaders.concat(styleLoaders)
540
+ },
541
+ {
542
+ use: cssLoaders.concat(styleLoaders)
543
+ }
544
+ ]
545
+ };
546
+ }
547
+ function createCssLoadersRule(ctx, cssLoaderOptions) {
548
+ const { options } = ctx;
549
+ const cssLoader = { loader: "css-loader", options: cssLoaderOptions };
550
+ if (options.webpack.extractCSS) {
551
+ if (ctx.isServer) {
552
+ if (cssLoader.options.modules) {
553
+ cssLoader.options.modules.exportOnlyLocals = cssLoader.options.modules.exportOnlyLocals ?? true;
554
+ }
555
+ return [cssLoader];
556
+ }
557
+ return [
558
+ {
559
+ loader: MiniCssExtractPlugin.loader
560
+ },
561
+ cssLoader
562
+ ];
563
+ }
564
+ return [
565
+ {
566
+ loader: "vue-style-loader",
567
+ options: options.webpack.loaders.vueStyle
568
+ },
569
+ cssLoader
570
+ ];
571
+ }
572
+ function createPostcssLoadersRule(ctx) {
573
+ const { options, nuxt } = ctx;
574
+ if (!options.postcss) {
575
+ return;
576
+ }
577
+ const config = getPostcssConfig(nuxt);
578
+ if (!config) {
579
+ return;
580
+ }
581
+ return {
582
+ loader: "postcss-loader",
583
+ options: config
584
+ };
585
+ }
586
+
587
+ const validate = (compiler) => {
588
+ if (compiler.options.target !== "node") {
589
+ logger.warn('webpack config `target` should be "node".');
590
+ }
591
+ if (!compiler.options.externals) {
592
+ logger.info("It is recommended to externalize dependencies in the server build for better build performance.");
593
+ }
594
+ };
595
+ const isJSRegExp = /\.[cm]?js(\?[^.]+)?$/;
596
+ const isJS = (file) => isJSRegExp.test(file);
597
+ const extractQueryPartJS = (file) => isJSRegExp.exec(file)[1];
598
+ const isCSS = (file) => /\.css(\?[^.]+)?$/.test(file);
599
+ const isHotUpdate = (file) => file.includes("hot-update");
600
+
601
+ class VueSSRClientPlugin {
602
+ constructor(options = {}) {
603
+ this.options = Object.assign({
604
+ filename: null
605
+ }, options);
606
+ }
607
+ apply(compiler) {
608
+ compiler.hooks.afterEmit.tap("VueSSRClientPlugin", async (compilation) => {
609
+ const stats = compilation.getStats().toJson();
610
+ const allFiles = uniq(stats.assets.map((a) => a.name)).filter((file) => !isHotUpdate(file));
611
+ const initialFiles = uniq(Object.keys(stats.entrypoints).map((name) => stats.entrypoints[name].assets).reduce((files, entryAssets) => files.concat(entryAssets.map((entryAsset) => entryAsset.name)), []).filter((file) => isJS(file) || isCSS(file))).filter((file) => !isHotUpdate(file));
612
+ const asyncFiles = allFiles.filter((file) => isJS(file) || isCSS(file)).filter((file) => !initialFiles.includes(file)).filter((file) => !isHotUpdate(file));
613
+ const assetsMapping = {};
614
+ stats.assets.filter(({ name }) => isJS(name)).filter(({ name }) => !isHotUpdate(name)).forEach(({ name, chunkNames }) => {
615
+ const componentHash = hash(chunkNames.join("|"));
616
+ if (!assetsMapping[componentHash]) {
617
+ assetsMapping[componentHash] = [];
618
+ }
619
+ assetsMapping[componentHash].push(name);
620
+ });
621
+ const manifest = {
622
+ publicPath: stats.publicPath,
623
+ all: allFiles,
624
+ initial: initialFiles,
625
+ async: asyncFiles,
626
+ modules: {},
627
+ assetsMapping
628
+ };
629
+ const { entrypoints, namedChunkGroups } = stats;
630
+ const assetModules = stats.modules.filter((m) => m.assets.length);
631
+ const fileToIndex = (file) => manifest.all.indexOf(file);
632
+ stats.modules.forEach((m) => {
633
+ if (m.chunks.length === 1) {
634
+ const [cid] = m.chunks;
635
+ const chunk = stats.chunks.find((c) => c.id === cid);
636
+ if (!chunk || !chunk.files) {
637
+ return;
638
+ }
639
+ const id = m.identifier.replace(/\s\w+$/, "");
640
+ const filesSet = new Set(chunk.files.map(fileToIndex).filter((i) => i !== -1));
641
+ for (const chunkName of chunk.names) {
642
+ if (!entrypoints[chunkName]) {
643
+ const chunkGroup = namedChunkGroups[chunkName];
644
+ if (chunkGroup) {
645
+ for (const asset of chunkGroup.assets) {
646
+ filesSet.add(fileToIndex(asset.name));
647
+ }
648
+ }
649
+ }
650
+ }
651
+ const files = Array.from(filesSet);
652
+ manifest.modules[hash(id)] = files;
653
+ if (Array.isArray(m.modules)) {
654
+ for (const concatenatedModule of m.modules) {
655
+ const id2 = hash(concatenatedModule.identifier.replace(/\s\w+$/, ""));
656
+ if (!manifest.modules[id2]) {
657
+ manifest.modules[id2] = files;
658
+ }
659
+ }
660
+ }
661
+ assetModules.forEach((m2) => {
662
+ if (m2.chunks.includes(cid)) {
663
+ files.push.apply(files, m2.assets.map(fileToIndex));
664
+ }
665
+ });
666
+ }
667
+ });
668
+ const src = JSON.stringify(manifest, null, 2);
669
+ await fse.mkdirp(dirname(this.options.filename));
670
+ await fse.writeFile(this.options.filename, src);
671
+ const mjsSrc = "export default " + src;
672
+ await fse.writeFile(this.options.filename.replace(".json", ".mjs"), mjsSrc);
673
+ });
674
+ }
675
+ }
676
+
677
+ class VueSSRServerPlugin {
678
+ constructor(options = {}) {
679
+ this.options = Object.assign({
680
+ filename: null
681
+ }, options);
682
+ }
683
+ apply(compiler) {
684
+ validate(compiler);
685
+ compiler.hooks.make.tap("VueSSRServerPlugin", (compilation) => {
686
+ compilation.hooks.processAssets.tapAsync({
687
+ name: "VueSSRServerPlugin",
688
+ stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
689
+ }, (assets, cb) => {
690
+ const stats = compilation.getStats().toJson();
691
+ const [entryName] = Object.keys(stats.entrypoints);
692
+ const entryInfo = stats.entrypoints[entryName];
693
+ if (!entryInfo) {
694
+ return cb();
695
+ }
696
+ const entryAssets = entryInfo.assets.filter((asset) => isJS(asset.name));
697
+ if (entryAssets.length > 1) {
698
+ throw new Error("Server-side bundle should have one single entry file. Avoid using CommonsChunkPlugin in the server config.");
699
+ }
700
+ const [entry] = entryAssets;
701
+ if (!entry || typeof entry.name !== "string") {
702
+ throw new Error(`Entry "${entryName}" not found. Did you specify the correct entry option?`);
703
+ }
704
+ const bundle = {
705
+ entry: entry.name,
706
+ files: {},
707
+ maps: {}
708
+ };
709
+ stats.assets.forEach((asset) => {
710
+ if (isJS(asset.name)) {
711
+ const queryPart = extractQueryPartJS(asset.name);
712
+ if (queryPart !== void 0) {
713
+ bundle.files[asset.name] = asset.name.replace(queryPart, "");
714
+ } else {
715
+ bundle.files[asset.name] = asset.name;
716
+ }
717
+ } else if (asset.name.match(/\.js\.map$/)) {
718
+ bundle.maps[asset.name.replace(/\.map$/, "")] = asset.name;
719
+ } else {
720
+ delete assets[asset.name];
721
+ }
722
+ });
723
+ const src = JSON.stringify(bundle, null, 2);
724
+ assets[this.options.filename] = {
725
+ source: () => src,
726
+ size: () => src.length
727
+ };
728
+ const mjsSrc = "export default " + src;
729
+ assets[this.options.filename.replace(".json", ".mjs")] = {
730
+ source: () => mjsSrc,
731
+ map: () => null,
732
+ size: () => mjsSrc.length
733
+ };
734
+ cb();
735
+ });
736
+ });
737
+ }
738
+ }
739
+
740
+ function vue(ctx) {
741
+ const { options, config } = ctx;
742
+ config.plugins.push(new (VueLoaderPlugin.default || VueLoaderPlugin)());
743
+ config.module.rules.push({
744
+ test: /\.vue$/i,
745
+ loader: "vue-loader",
746
+ options: {
747
+ reactivityTransform: ctx.nuxt.options.experimental.reactivityTransform,
748
+ ...options.webpack.loaders.vue
749
+ }
750
+ });
751
+ if (ctx.isClient) {
752
+ config.plugins.push(new VueSSRClientPlugin({
753
+ filename: resolve(options.buildDir, "dist/server", `${ctx.name}.manifest.json`)
754
+ }));
755
+ } else {
756
+ config.plugins.push(new VueSSRServerPlugin({
757
+ filename: `${ctx.name}.manifest.json`
758
+ }));
759
+ }
760
+ config.plugins.push(new webpack.DefinePlugin({
761
+ __VUE_OPTIONS_API__: "true",
762
+ __VUE_PROD_DEVTOOLS__: "false"
763
+ }));
764
+ }
765
+
766
+ function nuxt(ctx) {
767
+ applyPresets(ctx, [
768
+ base,
769
+ assets,
770
+ esbuild,
771
+ pug,
772
+ style,
773
+ vue
774
+ ]);
775
+ }
776
+
777
+ function client(ctx) {
778
+ ctx.name = "client";
779
+ ctx.isClient = true;
780
+ applyPresets(ctx, [
781
+ nuxt,
782
+ clientPlugins,
783
+ clientOptimization,
784
+ clientDevtool,
785
+ clientPerformance,
786
+ clientHMR
787
+ ]);
788
+ }
789
+ function clientDevtool(ctx) {
790
+ if (!ctx.isDev) {
791
+ ctx.config.devtool = false;
792
+ return;
793
+ }
794
+ const scriptPolicy = getCspScriptPolicy(ctx);
795
+ const noUnsafeEval = scriptPolicy && !scriptPolicy.includes("'unsafe-eval'");
796
+ ctx.config.devtool = noUnsafeEval ? "cheap-module-source-map" : "eval-cheap-module-source-map";
797
+ }
798
+ function clientPerformance(ctx) {
799
+ ctx.config.performance = {
800
+ maxEntrypointSize: 1e3 * 1024,
801
+ hints: ctx.isDev ? false : "warning",
802
+ ...ctx.config.performance
803
+ };
804
+ }
805
+ function clientHMR(ctx) {
806
+ const { options, config } = ctx;
807
+ if (!ctx.isDev) {
808
+ return;
809
+ }
810
+ const clientOptions = options.webpack.hotMiddleware?.client || {};
811
+ const hotMiddlewareClientOptions = {
812
+ reload: true,
813
+ timeout: 3e4,
814
+ path: joinURL(options.app.baseURL, "__webpack_hmr", ctx.name),
815
+ ...clientOptions,
816
+ ansiColors: JSON.stringify(clientOptions.ansiColors || {}),
817
+ overlayStyles: JSON.stringify(clientOptions.overlayStyles || {}),
818
+ name: ctx.name
819
+ };
820
+ const hotMiddlewareClientOptionsStr = querystring.stringify(hotMiddlewareClientOptions);
821
+ const app = config.entry.app;
822
+ app.unshift(`webpack-hot-middleware/client?${hotMiddlewareClientOptionsStr}`);
823
+ config.plugins.push(new webpack.HotModuleReplacementPlugin());
824
+ }
825
+ function clientOptimization(_ctx) {
826
+ }
827
+ function clientPlugins(ctx) {
828
+ const { options, config } = ctx;
829
+ if (!ctx.isDev && ctx.name === "client" && options.webpack.analyze) {
830
+ const statsDir = resolve(options.buildDir, "stats");
831
+ config.plugins.push(new BundleAnalyzerPlugin({
832
+ analyzerMode: "static",
833
+ defaultSizes: "gzip",
834
+ generateStatsFile: true,
835
+ openAnalyzer: !options.build.quiet,
836
+ reportFilename: resolve(statsDir, `${ctx.name}.html`),
837
+ statsFilename: resolve(statsDir, `${ctx.name}.json`),
838
+ ...options.webpack.analyze === true ? {} : options.webpack.analyze
839
+ }));
840
+ }
841
+ }
842
+ function getCspScriptPolicy(ctx) {
843
+ const { csp } = ctx.options.render;
844
+ if (typeof csp === "object") {
845
+ const { policies = {} } = csp;
846
+ return policies["script-src"] || policies["default-src"] || [];
847
+ }
848
+ }
849
+
850
+ function node(ctx) {
851
+ const { config } = ctx;
852
+ config.target = "node";
853
+ config.node = false;
854
+ config.experiments.outputModule = true;
855
+ config.output = {
856
+ ...config.output,
857
+ chunkFilename: "[name].mjs",
858
+ chunkFormat: "module",
859
+ chunkLoading: "import",
860
+ module: true,
861
+ environment: {
862
+ module: true,
863
+ arrowFunction: true,
864
+ bigIntLiteral: true,
865
+ const: true,
866
+ destructuring: true,
867
+ dynamicImport: true,
868
+ forOf: true
869
+ },
870
+ library: {
871
+ type: "module"
872
+ }
873
+ };
874
+ config.performance = {
875
+ ...config.performance,
876
+ hints: false,
877
+ maxEntrypointSize: Infinity,
878
+ maxAssetSize: Infinity
879
+ };
880
+ }
881
+
882
+ const assetPattern = /\.(css|s[ca]ss|png|jpe?g|gif|svg|woff2?|eot|ttf|otf|webp|webm|mp4|ogv)(\?.*)?$/i;
883
+ function server(ctx) {
884
+ ctx.name = "server";
885
+ ctx.isServer = true;
886
+ applyPresets(ctx, [
887
+ nuxt,
888
+ node,
889
+ serverStandalone,
890
+ serverPreset,
891
+ serverPlugins
892
+ ]);
893
+ return getWebpackConfig(ctx);
894
+ }
895
+ function serverPreset(ctx) {
896
+ const { config } = ctx;
897
+ config.output.filename = "server.mjs";
898
+ config.devtool = "cheap-module-source-map";
899
+ config.optimization = {
900
+ splitChunks: false,
901
+ minimize: false
902
+ };
903
+ }
904
+ function serverStandalone(ctx) {
905
+ const inline = [
906
+ "src/",
907
+ "#app",
908
+ "nuxt",
909
+ "nuxt3",
910
+ "!",
911
+ "-!",
912
+ "~",
913
+ "@/",
914
+ "#",
915
+ ...ctx.options.build.transpile
916
+ ];
917
+ const external = ["#internal/nitro"];
918
+ if (!Array.isArray(ctx.config.externals)) {
919
+ return;
920
+ }
921
+ ctx.config.externals.push(({ request }, cb) => {
922
+ if (external.includes(request)) {
923
+ return cb(null, true);
924
+ }
925
+ if (request[0] === "." || isAbsolute(request) || inline.find((prefix) => typeof prefix === "string" && request.startsWith(prefix)) || assetPattern.test(request)) {
926
+ return cb(null, false);
927
+ }
928
+ return cb(null, true);
929
+ });
930
+ }
931
+ function serverPlugins(ctx) {
932
+ const { config, options } = ctx;
933
+ if (options.webpack.serverURLPolyfill) {
934
+ config.plugins.push(new webpack.ProvidePlugin({
935
+ URL: [options.webpack.serverURLPolyfill, "URL"],
936
+ URLSearchParams: [options.webpack.serverURLPolyfill, "URLSearchParams"]
937
+ }));
938
+ }
939
+ if (ctx.nuxt.options.typescript.typeCheck === true || ctx.nuxt.options.typescript.typeCheck === "build" && !ctx.nuxt.options.dev) {
940
+ ctx.config.plugins.push(new ForkTSCheckerWebpackPlugin({ logger }));
941
+ }
942
+ }
943
+
944
+ async function bundle(nuxt) {
945
+ await registerVirtualModules();
946
+ const webpackConfigs = [client, ...nuxt.options.ssr ? [server] : []].map((preset) => {
947
+ const ctx = createWebpackConfigContext(nuxt);
948
+ applyPresets(ctx, preset);
949
+ return getWebpackConfig(ctx);
950
+ });
951
+ await nuxt.callHook("webpack:config", webpackConfigs);
952
+ const mfs = nuxt.options.dev ? createMFS() : null;
953
+ const compilers = webpackConfigs.map((config) => {
954
+ config.plugins.push(DynamicBasePlugin.webpack({
955
+ sourcemap: nuxt.options.sourcemap,
956
+ globalPublicPath: "__webpack_public_path__"
957
+ }));
958
+ const compiler = webpack(config);
959
+ if (nuxt.options.dev) {
960
+ compiler.outputFileSystem = mfs;
961
+ }
962
+ return compiler;
963
+ });
964
+ nuxt.hook("close", async () => {
965
+ for (const compiler of compilers) {
966
+ await new Promise((resolve) => compiler.close(resolve));
967
+ }
968
+ });
969
+ if (nuxt.options.dev) {
970
+ return Promise.all(compilers.map((c) => compile(c)));
971
+ }
972
+ for (const c of compilers) {
973
+ await compile(c);
974
+ }
975
+ }
976
+ async function createDevMiddleware(compiler) {
977
+ const nuxt = useNuxt();
978
+ logger.debug("Creating webpack middleware...");
979
+ const devMiddleware = pify(webpackDevMiddleware(compiler, {
980
+ publicPath: joinURL(nuxt.options.app.baseURL, nuxt.options.app.buildAssetsDir),
981
+ outputFileSystem: compiler.outputFileSystem,
982
+ stats: "none",
983
+ ...nuxt.options.webpack.devMiddleware
984
+ }));
985
+ nuxt.hook("close", () => pify(devMiddleware.close.bind(devMiddleware))());
986
+ const { client: _client, ...hotMiddlewareOptions } = nuxt.options.webpack.hotMiddleware || {};
987
+ const hotMiddleware = pify(webpackHotMiddleware(compiler, {
988
+ log: false,
989
+ heartbeat: 1e4,
990
+ path: joinURL(nuxt.options.app.baseURL, "__webpack_hmr", compiler.options.name),
991
+ ...hotMiddlewareOptions
992
+ }));
993
+ await nuxt.callHook("webpack:devMiddleware", devMiddleware);
994
+ await nuxt.callHook("webpack:hotMiddleware", hotMiddleware);
995
+ await nuxt.callHook("server:devMiddleware", async (req, res, next) => {
996
+ for (const mw of [devMiddleware, hotMiddleware]) {
997
+ await mw?.(req, res);
998
+ }
999
+ next();
1000
+ });
1001
+ return devMiddleware;
1002
+ }
1003
+ async function compile(compiler) {
1004
+ const nuxt = useNuxt();
1005
+ const { name } = compiler.options;
1006
+ await nuxt.callHook("build:compile", { name, compiler });
1007
+ compiler.hooks.done.tap("load-resources", async (stats2) => {
1008
+ await nuxt.callHook("build:compiled", { name, compiler, stats: stats2 });
1009
+ await nuxt.callHook("build:resources", compiler.outputFileSystem);
1010
+ });
1011
+ if (nuxt.options.dev) {
1012
+ const compilersWatching = [];
1013
+ nuxt.hook("close", async () => {
1014
+ await Promise.all(compilersWatching.map((watching) => pify(watching.close.bind(watching))()));
1015
+ });
1016
+ if (name === "client") {
1017
+ return new Promise((resolve, reject) => {
1018
+ compiler.hooks.done.tap("nuxt-dev", () => {
1019
+ resolve(null);
1020
+ });
1021
+ compiler.hooks.failed.tap("nuxt-errorlog", (err) => {
1022
+ reject(err);
1023
+ });
1024
+ createDevMiddleware(compiler).then((devMiddleware) => {
1025
+ compilersWatching.push(devMiddleware.context.watching);
1026
+ });
1027
+ });
1028
+ }
1029
+ return new Promise((resolve, reject) => {
1030
+ const watching = compiler.watch(nuxt.options.watchers.webpack, (err) => {
1031
+ if (err) {
1032
+ return reject(err);
1033
+ }
1034
+ resolve(null);
1035
+ });
1036
+ compilersWatching.push(watching);
1037
+ });
1038
+ }
1039
+ const stats = await new Promise((resolve, reject) => compiler.run((err, stats2) => err ? reject(err) : resolve(stats2)));
1040
+ if (stats.hasErrors()) {
1041
+ const error = new Error("Nuxt build error");
1042
+ if (nuxt.options.build.quiet === true) {
1043
+ error.stack = stats.toString("errors-only");
1044
+ }
1045
+ throw error;
1046
+ }
1047
+ await nuxt.callHook("build:resources");
1048
+ }
1049
+
1050
+ export { bundle };
package/package.json CHANGED
@@ -1,6 +1,73 @@
1
1
  {
2
2
  "name": "@nuxt/webpack-builder",
3
- "version": "0.10.0",
3
+ "version": "3.0.0-rc.2",
4
+ "repository": "nuxt/framework",
4
5
  "license": "MIT",
5
- "main": "./index.js"
6
+ "type": "module",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": "./dist/index.mjs",
10
+ "./dist/*": "./dist/*"
11
+ },
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "scripts": {
16
+ "prepack": "unbuild"
17
+ },
18
+ "dependencies": {
19
+ "@babel/core": "^7.17.10",
20
+ "@nuxt/friendly-errors-webpack-plugin": "^2.5.2",
21
+ "@nuxt/kit": "^3.0.0-rc.2",
22
+ "autoprefixer": "^10.4.7",
23
+ "css-loader": "^6.7.1",
24
+ "css-minimizer-webpack-plugin": "^3.4.1",
25
+ "cssnano": "^5.1.7",
26
+ "esbuild-loader": "^2.18.0",
27
+ "escape-string-regexp": "^5.0.0",
28
+ "file-loader": "^6.2.0",
29
+ "fork-ts-checker-webpack-plugin": "^7.2.11",
30
+ "fs-extra": "^10.1.0",
31
+ "hash-sum": "^2.0.0",
32
+ "lodash-es": "^4.17.21",
33
+ "magic-string": "^0.26.1",
34
+ "memfs": "^3.4.1",
35
+ "mini-css-extract-plugin": "^2.6.0",
36
+ "mlly": "^0.5.2",
37
+ "pathe": "^0.2.0",
38
+ "pify": "^5.0.0",
39
+ "postcss": "^8.4.13",
40
+ "postcss-import": "^14.1.0",
41
+ "postcss-loader": "^6.2.1",
42
+ "postcss-url": "^10.1.3",
43
+ "style-resources-loader": "^1.5.0",
44
+ "time-fix-plugin": "^2.0.7",
45
+ "ufo": "^0.8.3",
46
+ "unplugin": "^0.6.2",
47
+ "url-loader": "^4.1.1",
48
+ "vue-loader": "^17.0.0",
49
+ "vue-style-loader": "^4.1.3",
50
+ "webpack": "^5.72.0",
51
+ "webpack-bundle-analyzer": "^4.5.0",
52
+ "webpack-dev-middleware": "^5.3.1",
53
+ "webpack-hot-middleware": "^2.25.1",
54
+ "webpack-virtual-modules": "^0.4.3",
55
+ "webpackbar": "^5.0.2"
56
+ },
57
+ "devDependencies": {
58
+ "@nuxt/schema": "^3.0.0-rc.2",
59
+ "@types/pify": "^5.0.1",
60
+ "@types/webpack-bundle-analyzer": "^4.4.1",
61
+ "@types/webpack-dev-middleware": "^5.0.2",
62
+ "@types/webpack-hot-middleware": "^2.25.6",
63
+ "@types/webpack-virtual-modules": "^0",
64
+ "unbuild": "latest",
65
+ "vue": "3.2.33"
66
+ },
67
+ "peerDependencies": {
68
+ "vue": "3.2.33"
69
+ },
70
+ "engines": {
71
+ "node": "^14.16.0 || ^16.11.0 || ^17.0.0 || ^18.0.0"
72
+ }
6
73
  }
package/index.js DELETED
@@ -1 +0,0 @@
1
- throw new Error('This is a placeholder package. Please use `@nuxt/webpack-builder-edge`. Learn more: https://v3.nuxtjs.org')