fix(webpack): DeprecationWarning DEP_WEBPACK_COMPILATION_ASSETS (#57)

This commit is contained in:
Xin Du (Clark) 2020-09-30 13:03:13 +01:00 committed by GitHub
parent 5a7f5164f0
commit 20c2375e74

View File

@ -5,10 +5,15 @@
import hash from 'hash-sum' import hash from 'hash-sum'
import uniq from 'lodash/uniq' import uniq from 'lodash/uniq'
import { Compilation } from 'webpack'
import { isJS, isCSS } from './util' import { isJS, isCSS } from './util'
export default class VueSSRClientPlugin { export default class VueSSRClientPlugin {
options: {
filename: string
}
constructor (options = {}) { constructor (options = {}) {
this.options = Object.assign({ this.options = Object.assign({
filename: null filename: null
@ -16,96 +21,101 @@ export default class VueSSRClientPlugin {
} }
apply (compiler) { apply (compiler) {
compiler.hooks.emit.tapAsync('vue-client-plugin', (compilation, cb) => { compiler.hooks.make.tap('VueSSRClientPlugin', (compilation: any) => {
const stats = compilation.getStats().toJson() compilation.hooks.processAssets.tapAsync({
name: 'VueSSRClientPlugin',
stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
}, (assets, cb) => {
const stats = compilation.getStats().toJson()
const allFiles = uniq(stats.assets const allFiles = uniq(stats.assets
.map(a => a.name)) .map(a => a.name))
const initialFiles = uniq(Object.keys(stats.entrypoints) const initialFiles = uniq(Object.keys(stats.entrypoints)
.map(name => stats.entrypoints[name].assets) .map(name => stats.entrypoints[name].assets)
.reduce((files, entryAssets) => files.concat(entryAssets.map(entryAsset => entryAsset.name)), []) .reduce((files, entryAssets) => files.concat(entryAssets.map(entryAsset => entryAsset.name)), [])
.filter(file => isJS(file) || isCSS(file))) .filter(file => isJS(file) || isCSS(file)))
const asyncFiles = allFiles const asyncFiles = allFiles
.filter(file => isJS(file) || isCSS(file)) .filter(file => isJS(file) || isCSS(file))
.filter(file => !initialFiles.includes(file)) .filter(file => !initialFiles.includes(file))
const assetsMapping = {} const assetsMapping = {}
stats.assets stats.assets
.filter(({ name }) => isJS(name)) .filter(({ name }) => isJS(name))
.forEach(({ name, chunkNames }) => { .forEach(({ name, chunkNames }) => {
const componentHash = hash(chunkNames.join('|')) const componentHash = hash(chunkNames.join('|'))
if (!assetsMapping[componentHash]) { if (!assetsMapping[componentHash]) {
assetsMapping[componentHash] = [] assetsMapping[componentHash] = []
} }
assetsMapping[componentHash].push(name) assetsMapping[componentHash].push(name)
}) })
const manifest = { const manifest = {
publicPath: stats.publicPath, publicPath: stats.publicPath,
all: allFiles, all: allFiles,
initial: initialFiles, initial: initialFiles,
async: asyncFiles, async: asyncFiles,
modules: { /* [identifier: string]: Array<index: number> */ }, modules: { /* [identifier: string]: Array<index: number> */ },
assetsMapping assetsMapping
} }
const { entrypoints, namedChunkGroups } = stats const { entrypoints, namedChunkGroups } = stats
const assetModules = stats.modules.filter(m => m.assets.length) const assetModules = stats.modules.filter(m => m.assets.length)
const fileToIndex = file => manifest.all.indexOf(file) const fileToIndex = file => manifest.all.indexOf(file)
stats.modules.forEach((m) => { stats.modules.forEach((m) => {
// Ignore modules duplicated in multiple chunks // Ignore modules duplicated in multiple chunks
if (m.chunks.length === 1) { if (m.chunks.length === 1) {
const [cid] = m.chunks const [cid] = m.chunks
const chunk = stats.chunks.find(c => c.id === cid) const chunk = stats.chunks.find(c => c.id === cid)
if (!chunk || !chunk.files) { if (!chunk || !chunk.files) {
return return
} }
const id = m.identifier.replace(/\s\w+$/, '') // remove appended hash const id = m.identifier.replace(/\s\w+$/, '') // remove appended hash
const filesSet = new Set(chunk.files.map(fileToIndex)) const filesSet = new Set(chunk.files.map(fileToIndex))
for (const chunkName of chunk.names) { for (const chunkName of chunk.names) {
if (!entrypoints[chunkName]) { if (!entrypoints[chunkName]) {
const chunkGroup = namedChunkGroups[chunkName] const chunkGroup = namedChunkGroups[chunkName]
if (chunkGroup) { if (chunkGroup) {
for (const asset of chunkGroup.assets) { for (const asset of chunkGroup.assets) {
filesSet.add(fileToIndex(asset.name)) filesSet.add(fileToIndex(asset.name))
}
} }
} }
} }
}
const files = Array.from(filesSet) const files = Array.from(filesSet)
manifest.modules[hash(id)] = files manifest.modules[hash(id)] = files
// In production mode, modules may be concatenated by scope hoisting // In production mode, modules may be concatenated by scope hoisting
// Include ConcatenatedModule for not losing module-component mapping // Include ConcatenatedModule for not losing module-component mapping
if (Array.isArray(m.modules)) { if (Array.isArray(m.modules)) {
for (const concatenatedModule of m.modules) { for (const concatenatedModule of m.modules) {
const id = hash(concatenatedModule.identifier.replace(/\s\w+$/, '')) const id = hash(concatenatedModule.identifier.replace(/\s\w+$/, ''))
if (!manifest.modules[id]) { if (!manifest.modules[id]) {
manifest.modules[id] = files manifest.modules[id] = files
}
} }
} }
// Find all asset modules associated with the same chunk
assetModules.forEach((m) => {
if (m.chunks.some(id => id === cid)) {
files.push.apply(files, m.assets.map(fileToIndex))
}
})
} }
})
// Find all asset modules associated with the same chunk const src = JSON.stringify(manifest, null, 2)
assetModules.forEach((m) => {
if (m.chunks.some(id => id === cid)) { assets[this.options.filename] = {
files.push.apply(files, m.assets.map(fileToIndex)) source: () => src,
} size: () => src.length
})
} }
cb()
}) })
const src = JSON.stringify(manifest, null, 2)
compilation.assets[this.options.filename] = {
source: () => src,
size: () => src.length
}
cb()
}) })
} }
} }