Skip to content

Commit 9550751

Browse files
authored
Merge pull request #472 from neilime/patch-2
Fixes for webpack 5 support (backward compatible)
2 parents 961ad25 + a6d536c commit 9550751

File tree

2 files changed

+378
-363
lines changed

2 files changed

+378
-363
lines changed

lib/packExternalModules.js

Lines changed: 145 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -153,20 +153,25 @@ function findExternalOrigin(issuer) {
153153
}
154154

155155
function getExternalModules(stats) {
156+
if (!stats.compilation.chunks) {
157+
return [];
158+
}
156159
const externals = new Set();
160+
for (const chunk of stats.compilation.chunks) {
161+
if (!chunk.modulesIterable) {
162+
continue;
163+
}
157164

158-
_.forEach(stats.compilation.chunks, chunk => {
159165
// Explore each module within the chunk (built inputs):
160-
chunk.forEachModule(module => {
166+
for (const module of chunk.modulesIterable) {
161167
if (isExternalModule(module)) {
162168
externals.add({
163169
origin: _.get(findExternalOrigin(module.issuer), 'rawRequest'),
164170
external: getExternalModuleName(module)
165171
});
166172
}
167-
});
168-
});
169-
173+
}
174+
}
170175
return Array.from(externals);
171176
}
172177

@@ -206,146 +211,146 @@ module.exports = {
206211

207212
// Determine and create packager
208213
return BbPromise.try(() => Packagers.get.call(this, this.configuration.packager))
209-
.then(packager => {
210-
// Fetch needed original package.json sections
211-
const sectionNames = packager.copyPackageSectionNames;
212-
const packageJson = this.serverless.utils.readFileSync(packageJsonPath);
213-
const packageSections = _.pick(packageJson, sectionNames);
214-
if (!_.isEmpty(packageSections)) {
215-
this.options.verbose && this.serverless.cli.log(`Using package.json sections ${_.join(_.keys(packageSections), ', ')}`);
216-
}
214+
.then(packager => {
215+
// Fetch needed original package.json sections
216+
const sectionNames = packager.copyPackageSectionNames;
217+
const packageJson = this.serverless.utils.readFileSync(packageJsonPath);
218+
const packageSections = _.pick(packageJson, sectionNames);
219+
if (!_.isEmpty(packageSections)) {
220+
this.options.verbose && this.serverless.cli.log(`Using package.json sections ${_.join(_.keys(packageSections), ', ')}`);
221+
}
217222

218-
// Get first level dependency graph
219-
this.options.verbose && this.serverless.cli.log(`Fetch dependency graph from ${packageJsonPath}`);
223+
// Get first level dependency graph
224+
this.options.verbose && this.serverless.cli.log(`Fetch dependency graph from ${packageJsonPath}`);
220225

221-
return packager.getProdDependencies(path.dirname(packageJsonPath), 1)
222-
.then(dependencyGraph => {
223-
const problems = _.get(dependencyGraph, 'problems', []);
224-
if (this.options.verbose && !_.isEmpty(problems)) {
225-
this.serverless.cli.log(`Ignoring ${_.size(problems)} NPM errors:`);
226-
_.forEach(problems, problem => {
227-
this.serverless.cli.log(`=> ${problem}`);
228-
});
229-
}
230-
231-
// (1) Generate dependency composition
232-
const compositeModules = _.uniq(_.flatMap(stats.stats, compileStats => {
233-
const externalModules = _.concat(
234-
getExternalModules.call(this, compileStats),
235-
_.map(packageForceIncludes, whitelistedPackage => ({ external: whitelistedPackage }))
236-
);
237-
return getProdModules.call(this, externalModules, packagePath, dependencyGraph, packageForceExcludes);
238-
}));
239-
removeExcludedModules.call(this, compositeModules, packageForceExcludes, true);
240-
241-
if (_.isEmpty(compositeModules)) {
242-
// The compiled code does not reference any external modules at all
243-
this.serverless.cli.log('No external modules needed');
244-
return BbPromise.resolve();
245-
}
246-
247-
// (1.a) Install all needed modules
248-
const compositeModulePath = path.join(this.webpackOutputPath, 'dependencies');
249-
const compositePackageJson = path.join(compositeModulePath, 'package.json');
250-
251-
// (1.a.1) Create a package.json
252-
const compositePackage = _.defaults({
253-
name: this.serverless.service.service,
254-
version: '1.0.0',
255-
description: `Packaged externals for ${this.serverless.service.service}`,
256-
private: true,
257-
scripts: packageScripts
258-
}, packageSections);
259-
const relPath = path.relative(compositeModulePath, path.dirname(packageJsonPath));
260-
addModulesToPackageJson(compositeModules, compositePackage, relPath);
261-
this.serverless.utils.writeFileSync(compositePackageJson, JSON.stringify(compositePackage, null, 2));
262-
263-
// (1.a.2) Copy package-lock.json if it exists, to prevent unwanted upgrades
264-
const packageLockPath = path.join(path.dirname(packageJsonPath), packager.lockfileName);
265-
let hasPackageLock = false;
266-
return BbPromise.fromCallback(cb => fse.pathExists(packageLockPath, cb))
267-
.then(exists => {
268-
if (exists) {
269-
this.serverless.cli.log('Package lock found - Using locked versions');
270-
try {
271-
let packageLockFile = this.serverless.utils.readFileSync(packageLockPath);
272-
packageLockFile = packager.rebaseLockfile(relPath, packageLockFile);
273-
if (_.isObject(packageLockFile)) {
274-
packageLockFile = JSON.stringify(packageLockFile, null, 2);
275-
}
276-
277-
this.serverless.utils.writeFileSync(path.join(compositeModulePath, packager.lockfileName), packageLockFile);
278-
hasPackageLock = true;
279-
} catch(err) {
280-
this.serverless.cli.log(`Warning: Could not read lock file: ${err.message}`);
226+
return packager.getProdDependencies(path.dirname(packageJsonPath), 1)
227+
.then(dependencyGraph => {
228+
const problems = _.get(dependencyGraph, 'problems', []);
229+
if (this.options.verbose && !_.isEmpty(problems)) {
230+
this.serverless.cli.log(`Ignoring ${_.size(problems)} NPM errors:`);
231+
_.forEach(problems, problem => {
232+
this.serverless.cli.log(`=> ${problem}`);
233+
});
281234
}
282-
}
283-
return BbPromise.resolve();
284-
})
285-
.then(() => {
286-
const start = _.now();
287-
this.serverless.cli.log('Packing external modules: ' + compositeModules.join(', '));
288-
return packager.install(compositeModulePath, this.configuration.packagerOptions)
289-
.then(() => this.options.verbose && this.serverless.cli.log(`Package took [${_.now() - start} ms]`))
290-
.return(stats.stats);
291-
})
292-
.mapSeries(compileStats => {
293-
const modulePath = compileStats.compilation.compiler.outputPath;
294-
295-
// Create package.json
296-
const modulePackageJson = path.join(modulePath, 'package.json');
297-
const modulePackage = _.defaults({
298-
name: this.serverless.service.service,
299-
version: '1.0.0',
300-
description: `Packaged externals for ${this.serverless.service.service}`,
301-
private: true,
302-
scripts: packageScripts,
303-
dependencies: {}
304-
}, packageSections);
305-
const prodModules = getProdModules.call(this,
306-
_.concat(
307-
getExternalModules.call(this, compileStats),
308-
_.map(packageForceIncludes, whitelistedPackage => ({ external: whitelistedPackage }))
309-
), packagePath, dependencyGraph, packageForceExcludes);
310-
removeExcludedModules.call(this, prodModules, packageForceExcludes);
311-
const relPath = path.relative(modulePath, path.dirname(packageJsonPath));
312-
addModulesToPackageJson(prodModules, modulePackage, relPath);
313-
this.serverless.utils.writeFileSync(modulePackageJson, JSON.stringify(modulePackage, null, 2));
314-
315-
// GOOGLE: Copy modules only if not google-cloud-functions
316-
// GCF Auto installs the package json
317-
if (_.get(this.serverless, 'service.provider.name') === 'google') {
318-
return BbPromise.resolve();
319-
}
320-
321-
const startCopy = _.now();
322-
return BbPromise.try(() => {
323-
// Only copy dependency modules if demanded by packager
324-
if (packager.mustCopyModules) {
325-
return BbPromise.fromCallback(callback => fse.copy(path.join(compositeModulePath, 'node_modules'), path.join(modulePath, 'node_modules'), callback));
235+
236+
// (1) Generate dependency composition
237+
const compositeModules = _.uniq(_.flatMap(stats.stats, compileStats => {
238+
const externalModules = _.concat(
239+
getExternalModules.call(this, compileStats),
240+
_.map(packageForceIncludes, whitelistedPackage => ({ external: whitelistedPackage }))
241+
);
242+
return getProdModules.call(this, externalModules, packagePath, dependencyGraph, packageForceExcludes);
243+
}));
244+
removeExcludedModules.call(this, compositeModules, packageForceExcludes, true);
245+
246+
if (_.isEmpty(compositeModules)) {
247+
// The compiled code does not reference any external modules at all
248+
this.serverless.cli.log('No external modules needed');
249+
return BbPromise.resolve();
326250
}
327-
return BbPromise.resolve();
328-
})
329-
.then(() => hasPackageLock ?
330-
BbPromise.fromCallback(callback => fse.copy(path.join(compositeModulePath, packager.lockfileName), path.join(modulePath, packager.lockfileName), callback)) :
331-
BbPromise.resolve()
332-
)
333-
.tap(() => this.options.verbose && this.serverless.cli.log(`Copy modules: ${modulePath} [${_.now() - startCopy} ms]`))
334-
.then(() => {
335-
// Prune extraneous packages - removes not needed ones
336-
const startPrune = _.now();
337-
return packager.prune(modulePath, this.configuration.packagerOptions)
338-
.tap(() => this.options.verbose && this.serverless.cli.log(`Prune: ${modulePath} [${_.now() - startPrune} ms]`));
339-
})
340-
.then(() => {
341-
// Prune extraneous packages - removes not needed ones
342-
const startRunScripts = _.now();
343-
return packager.runScripts(modulePath, _.keys(packageScripts))
344-
.tap(() => this.options.verbose && this.serverless.cli.log(`Run scripts: ${modulePath} [${_.now() - startRunScripts} ms]`));
251+
252+
// (1.a) Install all needed modules
253+
const compositeModulePath = path.join(this.webpackOutputPath, 'dependencies');
254+
const compositePackageJson = path.join(compositeModulePath, 'package.json');
255+
256+
// (1.a.1) Create a package.json
257+
const compositePackage = _.defaults({
258+
name: this.serverless.service.service,
259+
version: '1.0.0',
260+
description: `Packaged externals for ${this.serverless.service.service}`,
261+
private: true,
262+
scripts: packageScripts
263+
}, packageSections);
264+
const relPath = path.relative(compositeModulePath, path.dirname(packageJsonPath));
265+
addModulesToPackageJson(compositeModules, compositePackage, relPath);
266+
this.serverless.utils.writeFileSync(compositePackageJson, JSON.stringify(compositePackage, null, 2));
267+
268+
// (1.a.2) Copy package-lock.json if it exists, to prevent unwanted upgrades
269+
const packageLockPath = path.join(path.dirname(packageJsonPath), packager.lockfileName);
270+
let hasPackageLock = false;
271+
return BbPromise.fromCallback(cb => fse.pathExists(packageLockPath, cb))
272+
.then(exists => {
273+
if (exists) {
274+
this.serverless.cli.log('Package lock found - Using locked versions');
275+
try {
276+
let packageLockFile = this.serverless.utils.readFileSync(packageLockPath);
277+
packageLockFile = packager.rebaseLockfile(relPath, packageLockFile);
278+
if (_.isObject(packageLockFile)) {
279+
packageLockFile = JSON.stringify(packageLockFile, null, 2);
280+
}
281+
282+
this.serverless.utils.writeFileSync(path.join(compositeModulePath, packager.lockfileName), packageLockFile);
283+
hasPackageLock = true;
284+
} catch (err) {
285+
this.serverless.cli.log(`Warning: Could not read lock file: ${err.message}`);
286+
}
287+
}
288+
return BbPromise.resolve();
289+
})
290+
.then(() => {
291+
const start = _.now();
292+
this.serverless.cli.log('Packing external modules: ' + compositeModules.join(', '));
293+
return packager.install(compositeModulePath, this.configuration.packagerOptions)
294+
.then(() => this.options.verbose && this.serverless.cli.log(`Package took [${_.now() - start} ms]`))
295+
.return(stats.stats);
296+
})
297+
.mapSeries(compileStats => {
298+
const modulePath = compileStats.compilation.compiler.outputPath;
299+
300+
// Create package.json
301+
const modulePackageJson = path.join(modulePath, 'package.json');
302+
const modulePackage = _.defaults({
303+
name: this.serverless.service.service,
304+
version: '1.0.0',
305+
description: `Packaged externals for ${this.serverless.service.service}`,
306+
private: true,
307+
scripts: packageScripts,
308+
dependencies: {}
309+
}, packageSections);
310+
const prodModules = getProdModules.call(this,
311+
_.concat(
312+
getExternalModules.call(this, compileStats),
313+
_.map(packageForceIncludes, whitelistedPackage => ({ external: whitelistedPackage }))
314+
), packagePath, dependencyGraph, packageForceExcludes);
315+
removeExcludedModules.call(this, prodModules, packageForceExcludes);
316+
const relPath = path.relative(modulePath, path.dirname(packageJsonPath));
317+
addModulesToPackageJson(prodModules, modulePackage, relPath);
318+
this.serverless.utils.writeFileSync(modulePackageJson, JSON.stringify(modulePackage, null, 2));
319+
320+
// GOOGLE: Copy modules only if not google-cloud-functions
321+
// GCF Auto installs the package json
322+
if (_.get(this.serverless, 'service.provider.name') === 'google') {
323+
return BbPromise.resolve();
324+
}
325+
326+
const startCopy = _.now();
327+
return BbPromise.try(() => {
328+
// Only copy dependency modules if demanded by packager
329+
if (packager.mustCopyModules) {
330+
return BbPromise.fromCallback(callback => fse.copy(path.join(compositeModulePath, 'node_modules'), path.join(modulePath, 'node_modules'), callback));
331+
}
332+
return BbPromise.resolve();
333+
})
334+
.then(() => hasPackageLock ?
335+
BbPromise.fromCallback(callback => fse.copy(path.join(compositeModulePath, packager.lockfileName), path.join(modulePath, packager.lockfileName), callback)) :
336+
BbPromise.resolve()
337+
)
338+
.tap(() => this.options.verbose && this.serverless.cli.log(`Copy modules: ${modulePath} [${_.now() - startCopy} ms]`))
339+
.then(() => {
340+
// Prune extraneous packages - removes not needed ones
341+
const startPrune = _.now();
342+
return packager.prune(modulePath, this.configuration.packagerOptions)
343+
.tap(() => this.options.verbose && this.serverless.cli.log(`Prune: ${modulePath} [${_.now() - startPrune} ms]`));
344+
})
345+
.then(() => {
346+
// Prune extraneous packages - removes not needed ones
347+
const startRunScripts = _.now();
348+
return packager.runScripts(modulePath, _.keys(packageScripts))
349+
.tap(() => this.options.verbose && this.serverless.cli.log(`Run scripts: ${modulePath} [${_.now() - startRunScripts} ms]`));
350+
});
351+
})
352+
.return();
345353
});
346-
})
347-
.return();
348354
});
349-
});
350355
}
351356
};

0 commit comments

Comments
 (0)