@omnia/tooling-vue
Version:
Used to bundle and serve manifests web component that build on Vue framework.
230 lines (229 loc) • 11.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.dynamicBundle = void 0;
const tslib_1 = require("tslib");
const path_1 = tslib_1.__importDefault(require("path"));
const vite_1 = require("vite");
const webpack_1 = require("webpack");
const fx_models_1 = require("@omnia/fx-models");
const base_1 = require("../base");
const utils_1 = require("../../utils");
const $ = tslib_1.__importStar(require("../../../../variables"));
function getWebpackResolveModulePath(stats, requestModulePath) {
let result = "";
stats.forEach(s => {
s.modules?.forEach(m => {
const foundReason = m.reasons?.find(r => r.userRequest === requestModulePath);
if (foundReason) {
result = m.id.toString();
return result;
}
});
});
return result;
}
exports.dynamicBundle = (0, base_1.defineTransformer)("omnia-bundle", () => {
const moduleMaps = {}; // bare import / relative path => module id
const bundleMaps = {}; // module id => resource id
const moduleMapResolvers = {};
return {
test(code, id, fileGraph) {
return utils_1.pathUtils.isJavaScriptSuperset(id);
},
async transform(code, id, fileGraph, ctx, fromWorker) {
//id.indexOf("wwwroot/docs/") === -1 &&
const dynamicModules = filterDynamicModules(fileGraph, ctx);
const bundledModules = dynamicModules.filter(item => item.resolved);
const unBundledModules = dynamicModules.filter(item => !item.resolved);
bundledModules.forEach(item => {
code = item.inject(code);
});
const nonResolvingModules = unBundledModules.filter(item => !moduleMaps[item.path]).map(item => ({ path: item.path, inject: item.inject }));
const nonResolvingModulePaths = Array.from(new Set(nonResolvingModules.map(item => item.path)));
const resolvingModules = unBundledModules.filter(item => !!moduleMaps[item.path]).map(item => moduleMaps[item.path].then(_ => {
code = item.inject(code);
}));
if (nonResolvingModulePaths.length == 0) {
await Promise.all(resolvingModules);
return code;
}
$.tooling.log(`[${fileGraph.id}] Found new dependencies:\n` + nonResolvingModulePaths.join('\n'));
$.tooling.log(`[${fileGraph.id}] Bundling dependencies...`);
const dynamicBundleResourceId = fx_models_1.Guid.newGuid().toString();
const entryPoint = {
['dynamicbundle_' + dynamicBundleResourceId]: nonResolvingModulePaths
};
nonResolvingModulePaths.forEach(modulePath => {
moduleMaps[modulePath] = new Promise(resolve => {
moduleMapResolvers[modulePath] = {
resolve: resolve,
resolved: false
};
});
});
await new Promise(function (resolve, reject) {
const configs = utils_1.webpackUtils.createWebpackConfig(entryPoint, 'dynamic');
const compiler = (0, webpack_1.webpack)(configs);
compiler.run((err, stats) => {
//console.log("compiler.run", err, stats)
if (stats.hasErrors()) {
$.tooling.log('HMR pre-bundle error : \r\n', $.tooling.LogTypes.Error);
let errors = stats.toJson().errors;
errors.forEach((err) => {
$.tooling.log(err.stack || err, $.tooling.LogTypes.Error);
});
reject();
return;
}
if (err) {
$.tooling.log(err, $.tooling.LogTypes.Error);
reject();
return;
}
nonResolvingModulePaths.forEach(modulePath => {
try {
const bareImport = modulePath.startsWith('.') ? false : true;
let relativePath = modulePath;
if (bareImport) {
relativePath = getWebpackResolveModulePath(stats.toJson().children, modulePath);
if (relativePath === "") {
throw new Error(`HMR pre-bundle error : can't resolve module path for ${modulePath}`);
}
}
const moduleId = bareImport ?
('./' + (0, vite_1.normalizePath)(relativePath.replace(utils_1.envUtils.getRootDirPath(), '.'))).toLowerCase() :
('./' + (0, vite_1.normalizePath)(path_1.default.dirname(relativePath)) + '/' + path_1.default.basename(relativePath, path_1.default.extname(relativePath)) + '.js').toLowerCase();
if (!bundleMaps[moduleId]) {
bundleMaps[moduleId] = dynamicBundleResourceId;
}
const depFileGraph = ctx.getFileGraph(modulePath);
if (!depFileGraph.js.bareImportVariable) {
depFileGraph.js.bareImportVariable = toRuntimeVariable(ctx.serviceId, bundleMaps[moduleId], moduleId);
depFileGraph.js.bareImportDynamicResourceId = bundleMaps[moduleId];
}
if (moduleMapResolvers[modulePath] && moduleMapResolvers[modulePath].resolved == false) {
moduleMapResolvers[modulePath].resolved = true;
moduleMapResolvers[modulePath].resolve(moduleId);
}
else if (!moduleMaps[modulePath]) {
moduleMaps[modulePath] = Promise.resolve(moduleId);
}
}
catch (err) {
console.error(`HMR pre-bundle error : module path ${modulePath} -> ${err}`);
}
});
Promise.all(resolvingModules).then(() => resolve());
//resolve();
});
});
nonResolvingModules.forEach(resolvedModule => {
code = resolvedModule.inject(code);
});
$.tooling.log(`[${fileGraph.id}] Bundle dependencies done`);
return code;
}
};
});
function filterDynamicModules(fileGraph, ctx) {
const requires = fileGraph.js.metadata.requires;
const imports = fileGraph.js.metadata.imports;
const esModules = [
...imports.defaultVariables.filter(item => filterBareImport(item, ctx)).map(item => ({
path: item.path,
resolved: isBareImportResolved(item, ctx),
inject(code) {
if (!code.includes(item.statement)) {
return code;
}
const depFileGraph = ctx.getFileGraph(item.path);
code = ensureBundleInjection(code, depFileGraph.js.bareImportDynamicResourceId);
code = utils_1.transformUtils.injectDefaultImportVariableDecleration(code);
return code.replace(item.statement, `const ${item.default} = ${utils_1.transformUtils.wrapDefaultImportVariable(depFileGraph.js.bareImportVariable)}`);
}
})),
...imports.namedVariables.filter(item => filterBareImport(item, ctx)).map(item => ({
path: item.path,
resolved: isBareImportResolved(item, ctx),
inject(code) {
if (!code.includes(item.statement)) {
return code;
}
const depFileGraph = ctx.getFileGraph(item.path);
const varString = item.values.join(', ');
const asVarString = Object.keys(item.asValues).map(k => `${k} as ${item.asValues[k]}`).join(', ');
const allVarString = varString.length > 0 && asVarString.length > 0 ?
[varString, asVarString].join(', ') :
varString.length > 0 ? varString : asVarString;
code = ensureBundleInjection(code, depFileGraph.js.bareImportDynamicResourceId);
return code.replace(item.statement, `const { ${allVarString} } = ${depFileGraph.js.bareImportVariable}`);
}
})),
...imports.noneVariables.filter(item => filterBareImport(item, ctx)).map(item => ({
path: item.path,
resolved: isBareImportResolved(item, ctx),
inject(code) {
if (!code.includes(item.statement)) {
return code;
}
const depFileGraph = ctx.getFileGraph(item.path);
code = ensureBundleInjection(code, depFileGraph.js.bareImportDynamicResourceId);
return code.replace(item.statement, depFileGraph.js.bareImportVariable);
}
})),
...imports.wildcardVariables.filter(item => filterBareImport(item, ctx)).map(item => ({
path: item.path,
resolved: isBareImportResolved(item, ctx),
inject(code) {
if (!code.includes(item.statement)) {
return code;
}
const depFileGraph = ctx.getFileGraph(item.path);
code = ensureBundleInjection(code, depFileGraph.js.bareImportDynamicResourceId);
return code.replace(item.statement, `const ${item.value} = ${depFileGraph.js.bareImportVariable}`);
}
}))
];
const cjsModules = requires.filter(item => filterBareImport(item, ctx)).map(item => ({
path: item.path,
resolved: isBareImportResolved(item, ctx),
inject(code) {
if (!code.includes(item.statement)) {
return code;
}
const depFileGraph = ctx.getFileGraph(item.path);
code = ensureBundleInjection(code, depFileGraph.js.bareImportDynamicResourceId);
code = utils_1.transformUtils.injectDefaultImportVariableDecleration(code);
return code.replace(item.statement, utils_1.transformUtils.wrapDefaultImportVariable(depFileGraph.js.bareImportVariable));
}
}));
// TODO: support re-export for bare imports
return [
...esModules,
...cjsModules
];
}
function ensureBundleInjection(code, resourceId) {
const injection = `import '${utils_1.pathUtils.HMR_DYNAMIC_BUNDLE_REQUEST}/${resourceId}'`;
if (code.includes(injection) == false) {
code = '\n' + injection + '\n' + code;
}
return code;
}
function filterBareImport(item, ctx) {
const depFileGraph = ctx.getFileGraph(item.path);
// skip omnia packages since they only contain typing files
return depFileGraph
&& depFileGraph.id.startsWith('./wwwroot/docs/') == false
&& depFileGraph.id.startsWith('@omnia') == false
&& !ctx.alias[depFileGraph.id]
&& depFileGraph.bareImport
&& depFileGraph.js;
}
function isBareImportResolved(item, ctx) {
const depFileGraph = ctx.getFileGraph(item.path);
return !!depFileGraph.js.bareImportVariable;
}
function toRuntimeVariable(serviceId, resourceId, moduleId) {
return `omniaWebpackJsonp['${serviceId}']['${resourceId}']('${moduleId}')`;
}