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

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