@zohodesk/client_build_tool
Version:
A CLI tool to build web applications and client libraries
223 lines (177 loc) • 7.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.I18nRuntimeDealerPlugin = void 0;
var _webpack = require("webpack");
var _htmlWebpackPlugin = _interopRequireDefault(require("html-webpack-plugin"));
var _constants = require("./constants");
var _getI18nLoadingRuntimeModule = require("./getI18nLoadingRuntimeModule");
var _templateFileName = require("./templateFileName");
var _hashUtils = require("./utils/hashUtils");
var _urlConcat = require("../../../../server/urlConcat");
var _I18nFilesEmitPlugin = require("./I18nFilesEmitPlugin");
var _LocaleChunkAssetsStore = require("./LocaleChunkAssetsStore");
var _logger = require("../../../../../logger");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const {
RawSource
} = _webpack.sources;
const pluginName = 'I18nRuntimeDealerPlugin'; // I18nExtractPlugin.loader = require.resolve('./loader');
class I18nRuntimeDealerPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
compiler.hooks.thisCompilation.tap(pluginName, compilation => {
// Get store for cache
this.store = (0, _LocaleChunkAssetsStore.getLocaleChunkAssetsStore)(compilation);
if (!this.options.runtime) {
return;
}
this.createI18nDownloadCodeInRuntimeFile(compilation);
this.addI18nIntoInitialHtml(compilation);
});
}
addI18nIntoInitialHtml(compilation) {
const i18nStore = this.store;
_htmlWebpackPlugin.default.getHooks(compilation).beforeAssetTagGeneration.tap(pluginName, hookOptions => {
const {
assets
} = hookOptions;
const {
templateLabel,
filename,
publicPath = '',
mainChunkName
} = this.options; // const dummyContent = '// dummy comment';
const dummyContentHash = 'dummy0content0hashes';
const entryPoint = compilation.entrypoints.get(mainChunkName);
const initialChunks = Array.from(entryPoint.chunks).filter(c => c.canBeInitial() && c.id !== c.runtime);
const initialI18nAssets = initialChunks.filter(c => i18nStore.isChunkHasI18n(c)).map(c => {
const data = _I18nFilesEmitPlugin.I18nFilesEmitPlugin.createFilenameWithHash({
compilation,
fileNameTemplate: filename,
chunk: c,
locale: templateLabel,
// NOTE: we used dummy content hash.
// Because we have no plan on use in content hash to initial I18n chunks
// So Dummy hash was being used it will not work just skip warnings
contentHash: dummyContentHash
});
return (0, _urlConcat.urlConcat)(publicPath, data.filename);
});
const allJSAssets = [...initialI18nAssets, ...assets.js].map(url => url.replaceAll('[locale]', templateLabel).replaceAll('%5Blocale%5D', templateLabel));
return {
assets: { ...assets,
js: allJSAssets
}
};
});
}
createI18nDownloadCodeInRuntimeFile(compilation) {
const {
chunkFilename,
locales,
localeVarName
} = this.options;
const chunkFilenameHasContentHash = (0, _hashUtils.hasContentHash)(chunkFilename);
const getI18nChunks = mainChunk => this.filterI18nUsedChunks(mainChunk.getAllAsyncChunks());
const I18nLoadingRuntimeModule = (0, _getI18nLoadingRuntimeModule.getI18nLoadingRuntimeModule)({
getI18nChunks
});
const enabledChunks = new WeakSet();
const chunkFilenameUrlGenerator = (i18nChunks, locale) => (0, _templateFileName.templateFileName)({
compilation,
localeVarName,
dynamicFilename: chunkFilename,
contentHashes: this.getContentHashes(locale),
chunks: i18nChunks
});
const prefixFunc = () => _constants.I18N_CHUNK_NAME_GENERATION_SEGMENT;
const handler = (entryRuntimeChunk, set) => {
if (enabledChunks.has(entryRuntimeChunk)) {
return;
}
enabledChunks.add(entryRuntimeChunk);
const {
chunkFilename,
// filename: initialFilename,
runtimeOptions
} = this.options;
if (typeof chunkFilename === 'string' && /\[(full)?hash(:\d+)?\]/.test(chunkFilename)) {
set.add(_webpack.RuntimeGlobals.getFullHash);
}
set.add(_webpack.RuntimeGlobals.publicPath);
compilation.addRuntimeModule(entryRuntimeChunk, new I18nLoadingRuntimeModule(set, {
prefixFunc: chunkFilenameHasContentHash ? prefixFunc : chunkFilenameUrlGenerator,
runtimeOptions,
chunkFilename
}));
};
compilation.hooks.runtimeRequirementInTree.for(_webpack.RuntimeGlobals.ensureChunkHandlers).tap(pluginName, handler);
if (chunkFilenameHasContentHash) {
compilation.hooks.processAssets.tap({
name: pluginName,
stage: _webpack.Compilation.PROCESS_ASSETS_STAGE_DERIVED // additionalAssets: true
}, assets => {
// eslint-disable-next-line no-underscore-dangle
const entries = compilation._getChunkGraphEntries();
function createRuntimeFilePerLocale({
locale,
runtimeFileName,
runtimeFileSourceStr,
i18nChunks
}) {
const newRuntimeName = runtimeFileName.replaceAll('[locale]', locale);
const replaceText = chunkFilenameUrlGenerator(i18nChunks, locale);
const replacedStr = runtimeFileSourceStr.replace(_constants.I18N_CHUNK_NAME_GENERATION_SEGMENT, replaceText);
compilation.emitAsset(newRuntimeName, new RawSource(replacedStr));
} // eslint-disable-next-line no-restricted-syntax
for (const entryChunk of entries) {
const i18nChunks = getI18nChunks(entryChunk);
const runtimeFileName = [...entryChunk.files][0];
const runtimeFileSourceStr = assets[runtimeFileName].source();
locales.forEach(locale => createRuntimeFilePerLocale({
locale,
entryChunk,
runtimeFileName,
runtimeFileSourceStr,
i18nChunks
})); // NOTE: we don't delete, Because of HTML plugin needs to add runtime file in html and efc
// compilation.deleteAsset(runtimeFileName);
}
});
compilation.hooks.processAssets.tap({
name: pluginName,
stage: _webpack.Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE // additionalAssets: true
}, () => {
// eslint-disable-next-line no-underscore-dangle
const entries = compilation._getChunkGraphEntries(); // eslint-disable-next-line no-restricted-syntax
for (const entryChunk of entries) {
const runtimeFileName = [...entryChunk.files][0] || '';
if (runtimeFileName.includes('runtime') && runtimeFileName.includes('[locale]')) {
(0, _logger.verboseLogger)('deleteAsset', runtimeFileName);
compilation.deleteAsset(runtimeFileName);
}
}
});
}
}
filterI18nUsedChunks(chunks) {
const i18nStore = this.store;
return Array.from(chunks).filter(c => i18nStore.isChunkHasI18n(c.id));
}
getContentHashes(locale) {
const i18nStore = this.store;
const contentHashes = {};
i18nStore.forEachChunkId(chunkId => {
const contentHash = i18nStore.getContentHash(chunkId, locale);
if (contentHash) {
contentHashes[chunkId] = contentHash;
}
}); // console.log({ contentHashes });
return contentHashes;
}
}
exports.I18nRuntimeDealerPlugin = I18nRuntimeDealerPlugin;