@hippy/hippy-dynamic-import-plugin
Advanced tools
Comparing version 1.0.0 to 2.0.0
189
index.js
const Template = require('webpack/lib/Template'); | ||
const UnsupportedFeatureWarning = require('webpack/lib/UnsupportedFeatureWarning'); | ||
@@ -6,2 +7,92 @@ class HippyDynamicLoadPlugin { | ||
apply(compiler) { | ||
compiler.hooks.compilation.tap( | ||
'CustomImportParserPlugin', | ||
(compilation, { normalModuleFactory }) => { | ||
const handler = (parser, parserOptions) => { | ||
if (parserOptions.import !== undefined && !parserOptions.import) return; | ||
parser.hooks.importCall.tap('CustomImportParserPlugin', (expr) => { | ||
if (expr.arguments.length !== 1) { | ||
throw new Error( | ||
"Incorrect number of arguments provided to 'import(module: string) -> Promise'.", | ||
); | ||
} | ||
const param = parser.evaluateExpression(expr.arguments[0]); | ||
// | ||
let chunkName = null; | ||
let mode = 'lazy'; | ||
const { | ||
options: importOptions, | ||
} = parser.parseCommentOptions(expr.range); | ||
if (importOptions) { | ||
if (importOptions.webpackChunkName !== undefined) { | ||
if (typeof importOptions.webpackChunkName !== 'string') { | ||
parser.state.module.warnings.push( | ||
new UnsupportedFeatureWarning( | ||
parser.state.module, | ||
`\`webpackChunkName\` expected a string, but received: ${importOptions.webpackChunkName}.`, | ||
expr.loc, | ||
), | ||
); | ||
} else { | ||
chunkName = importOptions.webpackChunkName; | ||
} | ||
} | ||
if (importOptions.webpackMode !== undefined) { | ||
if (typeof importOptions.webpackMode !== 'string') { | ||
parser.state.module.warnings.push( | ||
new UnsupportedFeatureWarning( | ||
parser.state.module, | ||
`\`webpackMode\` expected a string, but received: ${importOptions.webpackMode}.`, | ||
expr.loc, | ||
), | ||
); | ||
} else { | ||
mode = importOptions.webpackMode; | ||
} | ||
} | ||
} | ||
if (param.isString()) { | ||
if (mode !== 'lazy' && mode !== 'eager' && mode !== 'weak') { | ||
parser.state.module.warnings.push( | ||
new UnsupportedFeatureWarning( | ||
parser.state.module, | ||
`\`webpackMode\` expected 'lazy', 'eager' or 'weak', but received: ${mode}.`, | ||
expr.loc, | ||
), | ||
); | ||
} | ||
if (!['eager', 'weak'].includes(mode) && chunkName) { | ||
// eslint-disable-next-line no-underscore-dangle | ||
if (!global.__DYNAMIC_LOAD_MAP__) { | ||
// eslint-disable-next-line no-underscore-dangle | ||
global.__DYNAMIC_LOAD_MAP__ = { | ||
[chunkName]: importOptions.customChunkPath, | ||
}; | ||
} else { | ||
// eslint-disable-next-line no-underscore-dangle | ||
Object.assign(global.__DYNAMIC_LOAD_MAP__, { | ||
[chunkName]: importOptions.customChunkPath, | ||
}); | ||
} | ||
} | ||
} | ||
}); | ||
}; | ||
normalModuleFactory.hooks.parser | ||
.for('javascript/auto') | ||
.tap('ImportPlugin', handler); | ||
normalModuleFactory.hooks.parser | ||
.for('javascript/dynamic') | ||
.tap('ImportPlugin', handler); | ||
normalModuleFactory.hooks.parser | ||
.for('javascript/esm') | ||
.tap('ImportPlugin', handler); | ||
}, | ||
); | ||
compiler.hooks.make.tapAsync('HippyDynamicLoadPlugin', (compilation, callback) => { | ||
@@ -13,46 +104,66 @@ const tapsOfRequireEnsuer = compilation.mainTemplate.hooks.requireEnsure.taps; | ||
compilation.mainTemplate.hooks.requireEnsure.tap( | ||
'JsonpMainTemplatePlugin load', | ||
source => ( | ||
// const chunkLoadTimeout = compilation.mainTemplate.outputOptions.chunkLoadTimeout; | ||
Template.asString([source, | ||
'', | ||
'// JSONP chunk loading for javascript', | ||
'', | ||
'var installedChunkData = installedChunks[chunkId];', | ||
'if(installedChunkData !== 0) { // 0 means "already installed".', | ||
Template.indent(['', | ||
'// a Promise means "currently loading".', | ||
'if(installedChunkData) {', | ||
Template.indent(['promises.push(installedChunkData[2]);']), | ||
'} else {', | ||
Template.indent([ | ||
'// setup Promise in chunk cache', | ||
'var promise = new Promise(function(resolve, reject) {', | ||
'JsonpMainTemplatePlugin load', | ||
source => { | ||
// const chunkLoadTimeout = compilation.mainTemplate.outputOptions.chunkLoadTimeout; | ||
return Template.asString([source, | ||
'', | ||
'// JSONP chunk loading for javascript', | ||
'', | ||
'var installedChunkData = installedChunks[chunkId];', | ||
'if(installedChunkData !== 0) { // 0 means "already installed".', | ||
Template.indent(['', | ||
'// a Promise means "currently loading".', | ||
'if(installedChunkData) {', | ||
Template.indent(['promises.push(installedChunkData[2]);']), | ||
'} else {', | ||
Template.indent([ | ||
'installedChunkData = installedChunks[chunkId] = [resolve, reject];' | ||
]), | ||
'});', | ||
'promises.push(installedChunkData[2] = promise);', | ||
'', | ||
'// start chunk loading', | ||
'var path = jsonpScriptSrc(chunkId);', | ||
'onScriptComplete = function (error) {', | ||
Template.indent([ | ||
'if(error) {', | ||
'// setup Promise in chunk cache', | ||
'var promise = new Promise(function(resolve, reject) {', | ||
Template.indent([ | ||
'error.name = "ChunkLoadError";', | ||
'chunk[1](error);', | ||
'installedChunks[chunkId] = undefined;', | ||
'installedChunkData = installedChunks[chunkId] = [resolve, reject];' | ||
]), | ||
'}', | ||
'});', | ||
'promises.push(installedChunkData[2] = promise);', | ||
'', | ||
'// start chunk loading', | ||
global.__DYNAMIC_LOAD_MAP__ | ||
? `if(!global.__DYNAMIC_LOAD_MAP__) { | ||
try { | ||
global.__DYNAMIC_LOAD_MAP__ = JSON.parse('${JSON.stringify(global.__DYNAMIC_LOAD_MAP__)}'); | ||
} catch(err) { | ||
console.error('parse __DYNAMIC_LOAD_MAP__ error', err) | ||
}}` : "", | ||
`var path = jsonpScriptSrc(chunkId); | ||
if (path && global.__DYNAMIC_LOAD_MAP__) { | ||
var isSchema = ['https://', 'http://', '//'].some(schema => path.indexOf(schema) === 0); | ||
if(isSchema) { | ||
var pathList = path.split('/'); | ||
var chunkAllName = pathList[pathList.length -1]; | ||
var chunkName = chunkAllName.split('.')[0]; | ||
var customChunkPath = global.__DYNAMIC_LOAD_MAP__[chunkName]; | ||
if(customChunkPath) path = customChunkPath + chunkAllName; | ||
} else { | ||
var chunkName = path.split('.')[0]; | ||
var customChunkPath = global.__DYNAMIC_LOAD_MAP__[chunkName]; | ||
if(customChunkPath) path = customChunkPath + path; | ||
} | ||
}`, | ||
'onScriptComplete = function (error) {', | ||
Template.indent([ | ||
'if(error) {', | ||
Template.indent([ | ||
'error.name = "ChunkLoadError";', | ||
'chunk[1](error);', | ||
'installedChunks[chunkId] = undefined;', | ||
]), | ||
'}', | ||
]), | ||
'};', | ||
'global.dynamicLoad(path, onScriptComplete);', | ||
]), | ||
'};', | ||
'global.dynamicLoad(path, onScriptComplete);', | ||
'}', | ||
]), | ||
'}', | ||
]), | ||
'}', | ||
]) | ||
), | ||
]) | ||
}, | ||
); | ||
@@ -67,2 +178,2 @@ break; | ||
module.exports = HippyDynamicLoadPlugin; | ||
module.exports = HippyDynamicLoadPlugin; |
{ | ||
"name": "@hippy/hippy-dynamic-import-plugin", | ||
"version": "1.0.0", | ||
"version": "2.0.0", | ||
"description": "hippy webpack打包动态加载chunk包插件", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
# hippy-dynamic-import-plugin | ||
hippy webpack 打包动态加载chunk包插件 | ||
@@ -6,6 +7,9 @@ | ||
随着hippy业务越来越复杂,单独打包越来越大。为了减少首包大小,hippy 支持了`import()`进行拆包。业务可以按照需求进行拆包。 | ||
随着hippy业务越来越复杂,单独打包越来越大。为了减少首包大小,hippy 支持了`import()`进行动态加载分包。详细请参考 [Hippy 动态加载使用说明](https://hippyjs.org/#/guide/dynamic-import) | ||
## 支持版本 | ||
`hippy version >= 2.2` | ||
本地加载: `hippy version >= 2.2` | ||
http 加载: `hippy version >= 2.5.4` | ||
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
8995
167
15
1