@quasar/app-webpack
Version:
Quasar Framework App CLI with Webpack
134 lines (107 loc) • 3.58 kB
JavaScript
/*
* Forked from vue-server-renderer/client-plugin.js v2.6.12 NPM package
*/
const hash = require('hash-sum')
const { sources, Compilation } = require('webpack')
const jsRE = /\.js(\?[^.]+)?$/
const jsCssRE = /\.(js|css)($|\?)/
const swRE = /\s\w+$/
const hotUpdateRE = /\.hot-update\.js(on)?$/
const trailingSlashRE = /([^/])$/
const clientManifestFilename = '../quasar.manifest.json'
const uniq = arr => [...new Set(arr)]
function ensureTrailingSlash(path) {
return path === '' ? path : path.replace(trailingSlashRE, '$1/')
}
function groupFiles(fileList) {
const head = []
const body = []
for (const file of fileList) {
const target = jsRE.test(file) ? body : head
target.push(file)
}
return { h: head, b: body }
}
function getClientManifest(compilation) {
const stats = compilation.getStats().toJson()
const publicPath = ensureTrailingSlash(stats.publicPath)
const allFiles = uniq(
stats.assets
.map(a => a.name)
.filter(file => hotUpdateRE.test(file) === false)
)
const assetModules = stats.modules.filter(m => m.assets.length)
const initialFiles = uniq(
Object.keys(stats.entrypoints)
.map(name => stats.entrypoints[name].assets.map(entry => entry.name))
.reduce((assets, all) => all.concat(assets), [])
.filter(file => hotUpdateRE.test(file) === false)
)
const asyncFiles = allFiles.filter(
file => initialFiles.includes(file) === false
)
const manifest = {
publicPath,
initial: groupFiles(initialFiles),
modules: {}
}
stats.modules.forEach(m => {
// ignore modules duplicated in multiple chunks
if (m.chunks.length === 1) {
const cid = m.chunks[0]
const chunk = stats.chunks.find(c => c.id === cid)
if (!chunk || !chunk.files) return
const id = m.identifier.replace(swRE, '') // remove appended hash
const files = (manifest.modules[hash(id)] = chunk.files)
// find all asset modules associated with the same chunk
assetModules.forEach(mod => {
if (mod.chunks.some(item => item === cid)) {
files.push.apply(files, mod.assets)
}
})
}
})
const filterModuleFiles = file =>
asyncFiles.includes(file) || jsCssRE.test(file) === false
for (const moduleId in manifest.modules) {
const acc = {}
const { h, b } = groupFiles(
manifest.modules[moduleId].filter(filterModuleFiles)
)
if (h.length !== 0) acc.h = h
if (b.length !== 0) acc.b = b
if (h.length || b.length) {
manifest.modules[moduleId] = acc
} else {
delete manifest.modules[moduleId]
}
}
return manifest
}
module.exports.getClientManifest = getClientManifest
module.exports.QuasarSSRClientPlugin = class QuasarSSRClientPlugin {
apply(compiler) {
compiler.hooks.thisCompilation.tap(
'quasar-ssr-client-plugin',
compilation => {
compilation.hooks.processAssets.tapAsync(
{
name: 'quasar-ssr-client-plugin',
state: Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
},
(_, callback) => {
const manifest = getClientManifest(compilation)
const json = JSON.stringify(manifest, null, 2)
const content = new sources.RawSource(json)
if (compilation.getAsset(clientManifestFilename) !== void 0) {
compilation.updateAsset(clientManifestFilename, content)
} else {
compilation.emitAsset(clientManifestFilename, content)
}
callback()
}
)
}
)
}
}