mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-23 06:05:11 +00:00
142 lines
5.8 KiB
TypeScript
142 lines
5.8 KiB
TypeScript
// Based on https://github.com/webpack/webpack/blob/v4.46.0/lib/node/NodeMainTemplatePlugin.js#L81-L191
|
|
|
|
import { createRequire } from 'module'
|
|
import type { Compiler } from 'webpack'
|
|
export class AsyncLoadingPlugin {
|
|
private opts: any
|
|
private Template: any
|
|
constructor (opts) {
|
|
this.opts = opts
|
|
const _require = createRequire(import.meta.url)
|
|
const TemplatePath = _require.resolve('webpack/lib/Template', { paths: [...this.opts.modulesDir] })
|
|
this.Template = _require(TemplatePath)
|
|
}
|
|
|
|
apply (compiler: Compiler) {
|
|
compiler.hooks.compilation.tap('AsyncLoading', (compilation) => {
|
|
const mainTemplate = compilation.mainTemplate
|
|
mainTemplate.hooks.requireEnsure.tap(
|
|
'AsyncLoading',
|
|
(_source, chunk, hash) => {
|
|
const Template = this.Template
|
|
const chunkFilename = mainTemplate.outputOptions.chunkFilename
|
|
const chunkMaps = chunk.getChunkMaps()
|
|
const insertMoreModules = [
|
|
'var moreModules = chunk.modules, chunkIds = chunk.ids;',
|
|
'for(var moduleId in moreModules) {',
|
|
Template.indent(
|
|
mainTemplate.renderAddModule(
|
|
hash,
|
|
chunk,
|
|
'moduleId',
|
|
'moreModules[moduleId]'
|
|
)
|
|
),
|
|
'}'
|
|
]
|
|
return Template.asString([
|
|
'// Async chunk loading for Nitro',
|
|
'',
|
|
'var installedChunkData = installedChunks[chunkId];',
|
|
'if(installedChunkData !== 0) { // 0 means "already installed".',
|
|
Template.indent([
|
|
'// array of [resolve, reject, promise] means "currently loading"',
|
|
'if(installedChunkData) {',
|
|
Template.indent(['promises.push(installedChunkData[2]);']),
|
|
'} else {',
|
|
Template.indent([
|
|
'// load the chunk and return promise to it',
|
|
'var promise = new Promise(function(resolve, reject) {',
|
|
Template.indent([
|
|
'installedChunkData = installedChunks[chunkId] = [resolve, reject];',
|
|
'import(' +
|
|
mainTemplate.getAssetPath(
|
|
JSON.stringify(`./${chunkFilename}`),
|
|
{
|
|
hash: `" + ${mainTemplate.renderCurrentHashCode(
|
|
hash
|
|
)} + "`,
|
|
hashWithLength: length =>
|
|
`" + ${mainTemplate.renderCurrentHashCode(
|
|
hash,
|
|
length
|
|
)} + "`,
|
|
chunk: {
|
|
id: '" + chunkId + "',
|
|
hash: `" + ${JSON.stringify(
|
|
chunkMaps.hash
|
|
)}[chunkId] + "`,
|
|
hashWithLength: (length) => {
|
|
const shortChunkHashMap = {}
|
|
for (const chunkId of Object.keys(chunkMaps.hash)) {
|
|
if (typeof chunkMaps.hash[chunkId] === 'string') {
|
|
shortChunkHashMap[chunkId] = chunkMaps.hash[
|
|
chunkId
|
|
].substr(0, length)
|
|
}
|
|
}
|
|
return `" + ${JSON.stringify(
|
|
shortChunkHashMap
|
|
)}[chunkId] + "`
|
|
},
|
|
contentHash: {
|
|
javascript: `" + ${JSON.stringify(
|
|
chunkMaps.contentHash.javascript
|
|
)}[chunkId] + "`
|
|
},
|
|
contentHashWithLength: {
|
|
javascript: (length) => {
|
|
const shortContentHashMap = {}
|
|
const contentHash =
|
|
chunkMaps.contentHash.javascript
|
|
for (const chunkId of Object.keys(contentHash)) {
|
|
if (typeof contentHash[chunkId] === 'string') {
|
|
shortContentHashMap[chunkId] = contentHash[
|
|
chunkId
|
|
].substr(0, length)
|
|
}
|
|
}
|
|
return `" + ${JSON.stringify(
|
|
shortContentHashMap
|
|
)}[chunkId] + "`
|
|
}
|
|
},
|
|
name: `" + (${JSON.stringify(
|
|
chunkMaps.name
|
|
)}[chunkId]||chunkId) + "`
|
|
},
|
|
contentHashType: 'javascript'
|
|
}
|
|
) +
|
|
').then(chunk => {',
|
|
Template.indent(
|
|
insertMoreModules
|
|
.concat([
|
|
'var callbacks = [];',
|
|
'for(var i = 0; i < chunkIds.length; i++) {',
|
|
Template.indent([
|
|
'if(installedChunks[chunkIds[i]])',
|
|
Template.indent([
|
|
'callbacks = callbacks.concat(installedChunks[chunkIds[i]][0]);'
|
|
]),
|
|
'installedChunks[chunkIds[i]] = 0;'
|
|
]),
|
|
'}',
|
|
'for(i = 0; i < callbacks.length; i++)',
|
|
Template.indent('callbacks[i]();')
|
|
])
|
|
),
|
|
'});'
|
|
]),
|
|
'});',
|
|
'promises.push(installedChunkData[2] = promise);'
|
|
]),
|
|
'}'
|
|
]),
|
|
'}'
|
|
])
|
|
})
|
|
})
|
|
}
|
|
}
|