Skip to content

Commit

Permalink
Fix filesystem cache not working when package individually is set
Browse files Browse the repository at this point in the history
  • Loading branch information
hieuunguyeen committed Mar 24, 2022
1 parent ccc7345 commit af41bda
Show file tree
Hide file tree
Showing 2 changed files with 253 additions and 46 deletions.
142 changes: 96 additions & 46 deletions lib/compile.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,50 @@
'use strict';
"use strict";

const _ = require('lodash');
const BbPromise = require('bluebird');
const webpack = require('webpack');
const isBuiltinModule = require('is-builtin-module');
const logStats = require('./logStats');
const _ = require("lodash");
const BbPromise = require("bluebird");
const webpack = require("webpack");
const isBuiltinModule = require("is-builtin-module");
const logStats = require("./logStats");

function ensureArray(obj) {
return _.isArray(obj) ? obj : [obj];
}

function getStatsLogger(statsConfig, consoleLog, { log, ServerlessError }) {
return stats => {
return (stats) => {
logStats(stats, statsConfig, consoleLog, { log, ServerlessError });
};
}

function isIndividialPackaging() {
return _.get(this.serverless, "service.package.individually");
}

function getExternalModuleName(module) {
const pathArray = /^external .*"(.*?)"$/.exec(module.identifier());
if (!pathArray) {
throw new Error(`Unable to extract module name from Webpack identifier: ${module.identifier()}`);
throw new Error(
`Unable to extract module name from Webpack identifier: ${module.identifier()}`
);
}

const path = pathArray[1];
const pathComponents = path.split('/');
const pathComponents = path.split("/");
const main = pathComponents[0];

// this is a package within a namespace
if (main.charAt(0) == '@') {
if (main.charAt(0) == "@") {
return `${main}/${pathComponents[1]}`;
}

return main;
}

function isExternalModule(module) {
return _.startsWith(module.identifier(), 'external ') && !isBuiltinModule(getExternalModuleName(module));
return (
_.startsWith(module.identifier(), "external ") &&
!isBuiltinModule(getExternalModuleName(module))
);
}

/**
Expand All @@ -57,8 +66,11 @@ function getIssuerCompat(moduleGraph, module) {
* @param {Object} issuer - Module issuer
*/
function findExternalOrigin(moduleGraph, issuer) {
if (!_.isNil(issuer) && _.startsWith(issuer.rawRequest, './')) {
return findExternalOrigin(moduleGraph, getIssuerCompat(moduleGraph, issuer));
if (!_.isNil(issuer) && _.startsWith(issuer.rawRequest, "./")) {
return findExternalOrigin(
moduleGraph,
getIssuerCompat(moduleGraph, issuer)
);
}
return issuer;
}
Expand All @@ -69,52 +81,84 @@ function getExternalModules({ compilation }) {
if (isExternalModule(module)) {
externals.add({
origin: _.get(
findExternalOrigin(compilation.moduleGraph, getIssuerCompat(compilation.moduleGraph, module)),
'rawRequest'
findExternalOrigin(
compilation.moduleGraph,
getIssuerCompat(compilation.moduleGraph, module)
),
"rawRequest"
),
external: getExternalModuleName(module)
external: getExternalModuleName(module),
});
}
}
return Array.from(externals);
}

function webpackCompile(config, logStats) {
return BbPromise.fromCallback(cb => webpack(config).run(cb)).then(stats => {
// ensure stats in any array in the case of concurrent build.
stats = stats.stats ? stats.stats : [stats];
return BbPromise.fromCallback((cb) => webpack(config).run(cb)).then(
(stats) => {
// ensure stats in any array in the case of concurrent build.
stats = stats.stats ? stats.stats : [stats];

_.forEach(stats, logStats);
_.forEach(stats, logStats);

return _.map(stats, compileStats => ({
outputPath: compileStats.compilation.compiler.outputPath,
externalModules: getExternalModules(compileStats)
}));
});
return _.map(stats, (compileStats) => ({
outputPath: compileStats.compilation.compiler.outputPath,
externalModules: getExternalModules(compileStats),
}));
}
);
}

function webpackConcurrentCompile(configs, logStats, concurrency, ServerlessError) {
function webpackConcurrentCompile(
configs,
logStats,
concurrency,
ServerlessError
) {
const errors = [];
return BbPromise.map(
configs,
config =>
webpackCompile(config, logStats).catch(error => {
errors.push(error);
return error.stats;
}),
(config) => {
if (
isIndividialPackaging.call(this) &&
_.get(config, "cache.type") === "filesystem"
) {
const clonedConfig = _.clone(config);
const entryFunc = _.find(this.entryFunctions, [
"entry.key",
_.keys(config.entry)[0],
]);
clonedConfig.cache.name = entryFunc.func.name;
return webpackCompile(clonedConfig, logStats, ServerlessError).catch(
(error) => {
errors.push(error);
return error.stats;
}
);
}
return webpackCompile(config, logStats, ServerlessError).catch(
(error) => {
errors.push(error);
return error.stats;
}
);
},
{ concurrency }
).then(stats => {
).then((stats) => {
if (errors.length) {
if (!this.log) {
if (errors.length === 1) {
throw errors[0];
}
throw new ServerlessError('Webpack compilation errors, see stats above');
throw new ServerlessError(
"Webpack compilation errors, see stats above"
);
}
throw new ServerlessError(
`Webpack compilation failed:\n\n${_.join(
_.map(errors, error => error.message),
'\n\n'
_.map(errors, (error) => error.message),
"\n\n"
)}`
);
}
Expand All @@ -125,32 +169,38 @@ function webpackConcurrentCompile(configs, logStats, concurrency, ServerlessErro
module.exports = {
compile() {
if (this.log) {
this.log.verbose('[Webpack] Building with Webpack');
this.progress.get('webpack').update('[Webpack] Building with Webpack');
this.log.verbose("[Webpack] Building with Webpack");
this.progress.get("webpack").update("[Webpack] Building with Webpack");
} else {
this.serverless.cli.log('Bundling with Webpack...');
this.serverless.cli.log("Bundling with Webpack...");
}

const configs = ensureArray(this.webpackConfig);
if (configs[0] === undefined) {
return BbPromise.reject('Unable to find Webpack configuration');
return BbPromise.reject("Unable to find Webpack configuration");
}

const logStats = getStatsLogger(configs[0].stats, this.serverless.cli.consoleLog, {
log: this.log,
ServerlessError: this.serverless.classes.Error
});
const logStats = getStatsLogger(
configs[0].stats,
this.serverless.cli.consoleLog,
{
log: this.log,
ServerlessError: this.serverless.classes.Error,
}
);

if (!this.configuration) {
return BbPromise.reject(new this.serverless.classes.Error('Missing plugin configuration'));
return BbPromise.reject(
new this.serverless.classes.Error("Missing plugin configuration")
);
}
const concurrency = this.configuration.concurrency;

return webpackConcurrentCompile
.call(this, configs, logStats, concurrency, this.serverless.classes.Error)
.then(stats => {
.then((stats) => {
this.compileStats = { stats };
return BbPromise.resolve();
});
}
},
};

0 comments on commit af41bda

Please sign in to comment.