|
1 | 1 | 'use strict';
|
2 | 2 |
|
3 |
| -const isJS = (file) => /\.js(\?[^.]+)?$/.test(file); |
| 3 | +const isJS = (file) => /\.js(\?[^.]+)?$/.test(file); |
4 | 4 | const isCSS = (file) => /\.css(\?[^.]+)?$/.test(file);
|
5 | 5 |
|
6 |
| -const { red, yellow } = require('chalk'); |
7 |
| -const webpack = require('webpack'); |
8 |
| -const prefix = `[vue-server-renderer-webpack-plugin]`; |
9 |
| -exports.warn = msg => console.error(red(`${prefix} ${msg}\n`)); |
10 |
| -exports.tip = msg => console.log(yellow(`${prefix} ${msg}\n`)); |
11 |
| -const isWebpack5 = !!(webpack.version && webpack.version[0] > 4); |
12 |
| -const onEmit = (compiler, name, stageName, hook) => { |
13 |
| - if (isWebpack5) { |
14 |
| - // Webpack >= 5.0.0 |
15 |
| - compiler.hooks.compilation.tap(name, compilation => { |
16 |
| - if (compilation.compiler !== compiler) { |
17 |
| - // Ignore child compilers |
18 |
| - return; |
19 |
| - } |
20 |
| - const stage = webpack.Compilation[stageName]; |
21 |
| - compilation.hooks.processAssets.tapAsync({ name, stage }, (assets, cb) => { |
22 |
| - hook(compilation, cb); |
23 |
| - }); |
24 |
| - }); |
25 |
| - } |
26 |
| - else if (compiler.hooks) { |
27 |
| - // Webpack >= 4.0.0 |
28 |
| - compiler.hooks.emit.tapAsync(name, hook); |
29 |
| - } |
30 |
| - else { |
31 |
| - // Webpack < 4.0.0 |
32 |
| - compiler.plugin('emit', hook); |
33 |
| - } |
34 |
| -}; |
35 |
| -const stripModuleIdHash = id => { |
36 |
| - if (isWebpack5) { |
37 |
| - // Webpack >= 5.0.0 |
38 |
| - return id.replace(/\|\w+$/, ''); |
39 |
| - } |
40 |
| - // Webpack < 5.0.0 |
41 |
| - return id.replace(/\s\w+$/, ''); |
42 |
| -}; |
43 |
| -const getAssetName = asset => { |
44 |
| - if (typeof asset === 'string') { |
45 |
| - return asset; |
46 |
| - } |
47 |
| - return asset.name; |
| 6 | +const { red, yellow } = require('chalk'); |
| 7 | +const webpack = require('webpack'); |
| 8 | +const prefix = `[vue-server-renderer-webpack-plugin]`; |
| 9 | +exports.warn = msg => console.error(red(`${prefix} ${msg}\n`)); |
| 10 | +exports.tip = msg => console.log(yellow(`${prefix} ${msg}\n`)); |
| 11 | +const isWebpack5 = !!(webpack.version && webpack.version[0] > 4); |
| 12 | +const onEmit = (compiler, name, stageName, hook) => { |
| 13 | + if (isWebpack5) { |
| 14 | + // Webpack >= 5.0.0 |
| 15 | + compiler.hooks.compilation.tap(name, compilation => { |
| 16 | + if (compilation.compiler !== compiler) { |
| 17 | + // Ignore child compilers |
| 18 | + return; |
| 19 | + } |
| 20 | + const stage = webpack.Compilation[stageName]; |
| 21 | + compilation.hooks.processAssets.tapAsync({ name, stage }, (assets, cb) => { |
| 22 | + hook(compilation, cb); |
| 23 | + }); |
| 24 | + }); |
| 25 | + } |
| 26 | + else if (compiler.hooks) { |
| 27 | + // Webpack >= 4.0.0 |
| 28 | + compiler.hooks.emit.tapAsync(name, hook); |
| 29 | + } |
| 30 | + else { |
| 31 | + // Webpack < 4.0.0 |
| 32 | + compiler.plugin('emit', hook); |
| 33 | + } |
| 34 | +}; |
| 35 | +const stripModuleIdHash = id => { |
| 36 | + if (isWebpack5) { |
| 37 | + // Webpack >= 5.0.0 |
| 38 | + return id.replace(/\|\w+$/, ''); |
| 39 | + } |
| 40 | + // Webpack < 5.0.0 |
| 41 | + return id.replace(/\s\w+$/, ''); |
| 42 | +}; |
| 43 | +const getAssetName = asset => { |
| 44 | + if (typeof asset === 'string') { |
| 45 | + return asset; |
| 46 | + } |
| 47 | + return asset.name; |
48 | 48 | };
|
49 | 49 |
|
50 |
| -const hash = require("hash-sum"); |
51 |
| -const uniq = require("lodash.uniq"); |
52 |
| -class VueSSRClientPlugin { |
53 |
| - constructor(options = {}) { |
54 |
| - //@ts-expect-error no type on options |
55 |
| - this.options = Object.assign({ |
56 |
| - filename: "vue-ssr-client-manifest.json", |
57 |
| - }, options); |
58 |
| - } |
59 |
| - apply(compiler) { |
60 |
| - const stage = "PROCESS_ASSETS_STAGE_ADDITIONAL"; |
61 |
| - onEmit(compiler, "vue-client-plugin", stage, (compilation, cb) => { |
62 |
| - const stats = compilation.getStats().toJson(); |
63 |
| - const allFiles = uniq(stats.assets.map((a) => a.name)); |
64 |
| - const initialFiles = uniq(Object.keys(stats.entrypoints) |
65 |
| - .map((name) => stats.entrypoints[name].assets) |
66 |
| - .reduce((assets, all) => all.concat(assets), []) |
67 |
| - .map(getAssetName) |
68 |
| - .filter((file) => isJS(file) || isCSS(file))); |
69 |
| - const asyncFiles = allFiles |
70 |
| - .filter((file) => isJS(file) || isCSS(file)) |
71 |
| - .filter((file) => initialFiles.indexOf(file) < 0); |
72 |
| - const manifest = { |
73 |
| - publicPath: stats.publicPath, |
74 |
| - all: allFiles, |
75 |
| - initial: initialFiles, |
76 |
| - async: asyncFiles, |
77 |
| - modules: { |
78 |
| - /* [identifier: string]: Array<index: number> */ |
79 |
| - }, |
80 |
| - }; |
81 |
| - const assetModules = stats.modules.filter((m) => m.assets.length); |
82 |
| - const fileToIndex = (asset) => manifest.all.indexOf(getAssetName(asset)); |
83 |
| - stats.modules.forEach((m) => { |
84 |
| - // ignore modules duplicated in multiple chunks |
85 |
| - if (m.chunks.length === 1) { |
86 |
| - const cid = m.chunks[0]; |
87 |
| - const chunk = stats.chunks.find((c) => c.id === cid); |
88 |
| - if (!chunk || !chunk.files) { |
89 |
| - return; |
90 |
| - } |
91 |
| - const id = stripModuleIdHash(m.identifier); |
92 |
| - const files = (manifest.modules[hash(id)] = |
93 |
| - chunk.files.map(fileToIndex)); |
94 |
| - // find all asset modules associated with the same chunk |
95 |
| - assetModules.forEach((m) => { |
96 |
| - if (m.chunks.some((id) => id === cid)) { |
97 |
| - files.push.apply(files, m.assets.map(fileToIndex)); |
98 |
| - } |
99 |
| - }); |
100 |
| - } |
101 |
| - }); |
102 |
| - const json = JSON.stringify(manifest, null, 2); |
103 |
| - //@ts-expect-error no type on options |
104 |
| - compilation.assets[this.options.filename] = { |
105 |
| - source: () => json, |
106 |
| - size: () => json.length, |
107 |
| - }; |
108 |
| - cb(); |
109 |
| - }); |
110 |
| - } |
| 50 | +const hash = require("hash-sum"); |
| 51 | +const uniq = require("lodash.uniq"); |
| 52 | +class VueSSRClientPlugin { |
| 53 | + constructor(options = {}) { |
| 54 | + //@ts-expect-error no type on options |
| 55 | + this.options = Object.assign({ |
| 56 | + filename: "vue-ssr-client-manifest.json", |
| 57 | + }, options); |
| 58 | + } |
| 59 | + apply(compiler) { |
| 60 | + const stage = "PROCESS_ASSETS_STAGE_ADDITIONAL"; |
| 61 | + onEmit(compiler, "vue-client-plugin", stage, (compilation, cb) => { |
| 62 | + const stats = compilation.getStats().toJson(); |
| 63 | + const allFiles = uniq(stats.assets.map((a) => a.name)); |
| 64 | + const initialFiles = uniq(Object.keys(stats.entrypoints) |
| 65 | + .map((name) => stats.entrypoints[name].assets) |
| 66 | + .reduce((assets, all) => all.concat(assets), []) |
| 67 | + .map(getAssetName) |
| 68 | + .filter((file) => isJS(file) || isCSS(file))); |
| 69 | + const asyncFiles = allFiles |
| 70 | + .filter((file) => isJS(file) || isCSS(file)) |
| 71 | + .filter((file) => initialFiles.indexOf(file) < 0); |
| 72 | + const manifest = { |
| 73 | + publicPath: stats.publicPath, |
| 74 | + all: allFiles, |
| 75 | + initial: initialFiles, |
| 76 | + async: asyncFiles, |
| 77 | + modules: { |
| 78 | + /* [identifier: string]: Array<index: number> */ |
| 79 | + }, |
| 80 | + }; |
| 81 | + const assetModules = stats.modules.filter((m) => m.assets.length); |
| 82 | + const fileToIndex = (asset) => manifest.all.indexOf(getAssetName(asset)); |
| 83 | + stats.modules.forEach((m) => { |
| 84 | + // ignore modules duplicated in multiple chunks |
| 85 | + if (m.chunks.length === 1) { |
| 86 | + const cid = m.chunks[0]; |
| 87 | + const chunk = stats.chunks.find((c) => c.id === cid); |
| 88 | + if (!chunk || !chunk.files) { |
| 89 | + return; |
| 90 | + } |
| 91 | + const id = stripModuleIdHash(m.identifier); |
| 92 | + const files = (manifest.modules[hash(id)] = |
| 93 | + chunk.files.map(fileToIndex)); |
| 94 | + // find all asset modules associated with the same chunk |
| 95 | + assetModules.forEach((m) => { |
| 96 | + if (m.chunks.some((id) => id === cid)) { |
| 97 | + files.push.apply(files, m.assets.map(fileToIndex)); |
| 98 | + } |
| 99 | + }); |
| 100 | + } |
| 101 | + }); |
| 102 | + const json = JSON.stringify(manifest, null, 2); |
| 103 | + //@ts-expect-error no type on options |
| 104 | + compilation.assets[this.options.filename] = { |
| 105 | + source: () => json, |
| 106 | + size: () => json.length, |
| 107 | + }; |
| 108 | + cb(); |
| 109 | + }); |
| 110 | + } |
111 | 111 | }
|
112 | 112 |
|
113 | 113 | module.exports = VueSSRClientPlugin;
|
0 commit comments