mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-13 09:33:54 +00:00
fix(build): use last hash file name in client manifest (#123)
This commit is contained in:
parent
3d06693f88
commit
8e320f80aa
@ -7,7 +7,6 @@ import { dirname } from 'path'
|
|||||||
import hash from 'hash-sum'
|
import hash from 'hash-sum'
|
||||||
import uniq from 'lodash/uniq'
|
import uniq from 'lodash/uniq'
|
||||||
import { writeFile, mkdirp } from 'fs-extra'
|
import { writeFile, mkdirp } from 'fs-extra'
|
||||||
import { Compilation } from 'webpack'
|
|
||||||
|
|
||||||
import { isJS, isCSS } from './util'
|
import { isJS, isCSS } from './util'
|
||||||
|
|
||||||
@ -23,104 +22,97 @@ export default class VueSSRClientPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
apply (compiler) {
|
apply (compiler) {
|
||||||
compiler.hooks.make.tap('VueSSRClientPlugin', (compilation: any) => {
|
compiler.hooks.afterEmit.tap('VueSSRClientPlugin', async (compilation: any) => {
|
||||||
compilation.hooks.processAssets.tapAsync({
|
const stats = compilation.getStats().toJson()
|
||||||
name: 'VueSSRClientPlugin',
|
|
||||||
stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
|
|
||||||
}, async (_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)
|
|
||||||
})
|
|
||||||
|
|
||||||
const manifest = {
|
|
||||||
publicPath: stats.publicPath,
|
|
||||||
all: allFiles,
|
|
||||||
initial: initialFiles,
|
|
||||||
async: asyncFiles,
|
|
||||||
modules: { /* [identifier: string]: Array<index: number> */ },
|
|
||||||
assetsMapping
|
|
||||||
}
|
|
||||||
|
|
||||||
const { entrypoints, namedChunkGroups } = stats
|
|
||||||
const assetModules = stats.modules.filter(m => m.assets.length)
|
|
||||||
const fileToIndex = file => manifest.all.indexOf(file)
|
|
||||||
stats.modules.forEach((m) => {
|
|
||||||
// Ignore modules duplicated in multiple chunks
|
|
||||||
if (m.chunks.length === 1) {
|
|
||||||
const [cid] = m.chunks
|
|
||||||
const chunk = stats.chunks.find(c => c.id === cid)
|
|
||||||
if (!chunk || !chunk.files) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const id = m.identifier.replace(/\s\w+$/, '') // remove appended hash
|
|
||||||
const filesSet = new Set(chunk.files.map(fileToIndex))
|
|
||||||
|
|
||||||
for (const chunkName of chunk.names) {
|
|
||||||
if (!entrypoints[chunkName]) {
|
|
||||||
const chunkGroup = namedChunkGroups[chunkName]
|
|
||||||
if (chunkGroup) {
|
|
||||||
for (const asset of chunkGroup.assets) {
|
|
||||||
filesSet.add(fileToIndex(asset.name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const files = Array.from(filesSet)
|
|
||||||
manifest.modules[hash(id)] = files
|
|
||||||
|
|
||||||
// In production mode, modules may be concatenated by scope hoisting
|
|
||||||
// Include ConcatenatedModule for not losing module-component mapping
|
|
||||||
if (Array.isArray(m.modules)) {
|
|
||||||
for (const concatenatedModule of m.modules) {
|
|
||||||
const id = hash(concatenatedModule.identifier.replace(/\s\w+$/, ''))
|
|
||||||
if (!manifest.modules[id]) {
|
|
||||||
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))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
assetsMapping[componentHash].push(name)
|
||||||
})
|
})
|
||||||
|
|
||||||
const src = JSON.stringify(manifest, null, 2)
|
const manifest = {
|
||||||
|
publicPath: stats.publicPath,
|
||||||
|
all: allFiles,
|
||||||
|
initial: initialFiles,
|
||||||
|
async: asyncFiles,
|
||||||
|
modules: { /* [identifier: string]: Array<index: number> */ },
|
||||||
|
assetsMapping
|
||||||
|
}
|
||||||
|
|
||||||
await mkdirp(dirname(this.options.filename))
|
const { entrypoints, namedChunkGroups } = stats
|
||||||
await writeFile(this.options.filename, src)
|
const assetModules = stats.modules.filter(m => m.assets.length)
|
||||||
// assets[this.options.filename] = {
|
const fileToIndex = file => manifest.all.indexOf(file)
|
||||||
// source: () => src,
|
stats.modules.forEach((m) => {
|
||||||
// size: () => src.length
|
// Ignore modules duplicated in multiple chunks
|
||||||
// }
|
if (m.chunks.length === 1) {
|
||||||
|
const [cid] = m.chunks
|
||||||
|
const chunk = stats.chunks.find(c => c.id === cid)
|
||||||
|
if (!chunk || !chunk.files) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const id = m.identifier.replace(/\s\w+$/, '') // remove appended hash
|
||||||
|
const filesSet = new Set(chunk.files.map(fileToIndex))
|
||||||
|
|
||||||
cb()
|
for (const chunkName of chunk.names) {
|
||||||
|
if (!entrypoints[chunkName]) {
|
||||||
|
const chunkGroup = namedChunkGroups[chunkName]
|
||||||
|
if (chunkGroup) {
|
||||||
|
for (const asset of chunkGroup.assets) {
|
||||||
|
filesSet.add(fileToIndex(asset.name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const files = Array.from(filesSet)
|
||||||
|
manifest.modules[hash(id)] = files
|
||||||
|
|
||||||
|
// In production mode, modules may be concatenated by scope hoisting
|
||||||
|
// Include ConcatenatedModule for not losing module-component mapping
|
||||||
|
if (Array.isArray(m.modules)) {
|
||||||
|
for (const concatenatedModule of m.modules) {
|
||||||
|
const id = hash(concatenatedModule.identifier.replace(/\s\w+$/, ''))
|
||||||
|
if (!manifest.modules[id]) {
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const src = JSON.stringify(manifest, null, 2)
|
||||||
|
|
||||||
|
await mkdirp(dirname(this.options.filename))
|
||||||
|
await writeFile(this.options.filename, src)
|
||||||
|
// assets[this.options.filename] = {
|
||||||
|
// source: () => src,
|
||||||
|
// size: () => src.length
|
||||||
|
// }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user