UNPKG

@zohodesk/client_build_tool

Version:

A CLI tool to build web applications and client libraries

223 lines (177 loc) 7.5 kB
"use strict"; 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;