Skip to content

Commit 152d1cf

Browse files
authored
Merge pull request #2409 from serverless-heaven/fix/remove-bluebird
Remove bluebird and use native Promise
2 parents 1b2f2ee + 4485456 commit 152d1cf

32 files changed

Lines changed: 2810 additions & 2677 deletions

README.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,15 +128,14 @@ module.exports = (async () => {
128128
```
129129

130130
```js
131-
// Version with promises
131+
// Version with native promises
132132
// webpack.config.js
133133

134134
const webpack = require('webpack')
135135
const slsw = require('serverless-webpack');
136-
const BbPromise = require('bluebird');
137136

138-
module.exports = BbPromise.try(() => {
139-
return slsw.lib.serverless.providers.aws.getAccountId()
137+
module.exports = Promise.resolve()
138+
.then(() => slsw.lib.serverless.providers.aws.getAccountId())
140139
.then(accountId => ({
141140
entry: './handler.js',
142141
target: 'node',
@@ -149,7 +148,6 @@ module.exports = BbPromise.try(() => {
149148
loaders: [ ... ]
150149
}
151150
}));
152-
});
153151
```
154152

155153
### serverless-webpack lib export helper

__mocks__/fs.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,18 @@ const streamMock = {
77
};
88

99
const statMock = {
10-
isDirectory: jest.fn()
10+
isDirectory: jest.fn(),
11+
mode: 0o644
1112
};
1213

1314
const actual = jest.requireActual('fs');
1415

1516
module.exports = {
1617
...actual,
1718
createWriteStream: jest.fn().mockReturnValue(streamMock),
19+
readFile: jest.fn((_path, callback) => callback(null, Buffer.from('mock file'))),
1820
readFileSync: jest.fn(),
21+
stat: jest.fn((_path, callback) => callback(null, statMock)),
1922
statSync: jest.fn().mockReturnValue(statMock),
2023
writeFileSync: jest.fn(),
2124
copyFileSync: jest.fn(),

biome.jsonc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"$schema": "https://biomejs.dev/schemas/2.4.5/schema.json",
2+
"$schema": "https://biomejs.dev/schemas/2.4.12/schema.json",
33
"vcs": {
44
"enabled": true,
55
"clientKind": "git",

index.js

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
const BbPromise = require('bluebird');
21
const _ = require('lodash');
32

43
const validate = require('./lib/validate');
@@ -150,13 +149,13 @@ class ServerlessWebpack {
150149
}
151150
},
152151
'before:package:createDeploymentArtifacts': () =>
153-
BbPromise.bind(this)
152+
Promise.resolve()
154153
.then(() => this.serverless.pluginManager.spawn('webpack:validate'))
155-
.then(() => (this.skipCompile ? BbPromise.resolve() : this.serverless.pluginManager.spawn('webpack:compile')))
154+
.then(() => (this.skipCompile ? undefined : this.serverless.pluginManager.spawn('webpack:compile')))
156155
.then(() => this.serverless.pluginManager.spawn('webpack:package'))
157156
.then(() => this.log && this.progress.get('webpack').remove()),
158157

159-
'after:package:createDeploymentArtifacts': () => BbPromise.bind(this).then(this.cleanup),
158+
'after:package:createDeploymentArtifacts': () => Promise.resolve().then(() => this.cleanup()),
160159

161160
'before:deploy:function:packageFunction': () => {
162161
const runtime =
@@ -165,98 +164,96 @@ class ServerlessWebpack {
165164
'nodejs';
166165

167166
if (isNodeRuntime(runtime)) {
168-
return BbPromise.bind(this)
167+
return Promise.resolve()
169168
.then(() => this.serverless.pluginManager.spawn('webpack:validate'))
170169
.then(() => this.serverless.pluginManager.spawn('webpack:compile'))
171170
.then(() => this.serverless.pluginManager.spawn('webpack:package'));
172171
}
173172
},
174173

175174
'before:invoke:local:invoke': () =>
176-
BbPromise.bind(this)
175+
Promise.resolve()
177176
.then(() => {
178177
lib.webpack.isLocal = true;
179178

180179
return this.serverless.pluginManager.spawn('webpack:validate');
181180
})
182-
.then(() => (this.skipCompile ? BbPromise.resolve() : this.serverless.pluginManager.spawn('webpack:compile')))
183-
.then(this.prepareLocalInvoke),
181+
.then(() => (this.skipCompile ? undefined : this.serverless.pluginManager.spawn('webpack:compile')))
182+
.then(() => this.prepareLocalInvoke()),
184183

185184
'after:invoke:local:invoke': () =>
186-
BbPromise.bind(this).then(() => {
185+
Promise.resolve().then(() => {
187186
if (this.options.watch && !this.isWatching) {
188187
return this.watch('invoke:local');
189188
}
190-
return BbPromise.resolve();
191189
}),
192190

193191
'before:run:run': () =>
194-
BbPromise.bind(this)
192+
Promise.resolve()
195193
.then(() => _.set(this.serverless, 'service.package.individually', false))
196194
.then(() => this.serverless.pluginManager.spawn('webpack:validate'))
197195
.then(() => this.serverless.pluginManager.spawn('webpack:compile'))
198-
.then(this.packExternalModules)
199-
.then(this.prepareRun),
196+
.then(() => this.packExternalModules())
197+
.then(() => this.prepareRun()),
200198

201199
'after:run:run': () =>
202-
BbPromise.bind(this).then(() => {
200+
Promise.resolve().then(() => {
203201
if (this.options.watch && !this.isWatching) {
204202
return this.watch(this.watchRun.bind(this));
205203
}
206-
return BbPromise.resolve();
207204
}),
208205

209206
'webpack:webpack': () =>
210-
BbPromise.bind(this)
207+
Promise.resolve()
211208
.then(() => this.serverless.pluginManager.spawn('webpack:validate'))
212209
.then(() => this.serverless.pluginManager.spawn('webpack:compile'))
213210
.then(() => this.serverless.pluginManager.spawn('webpack:package')),
214211

215212
/*
216213
* Internal webpack events (can be hooked by plugins)
217214
*/
218-
'webpack:validate:validate': () => BbPromise.bind(this).then(this.validate),
215+
'webpack:validate:validate': () => Promise.resolve().then(() => this.validate()),
219216

220-
'webpack:compile:compile': () => BbPromise.bind(this).then(this.compile),
217+
'webpack:compile:compile': () => Promise.resolve().then(() => this.compile()),
221218

222-
'webpack:compile:watch:compile': () => BbPromise.resolve(),
219+
'webpack:compile:watch:compile': () => Promise.resolve(),
223220

224-
'webpack:package:packExternalModules': () => BbPromise.bind(this).then(this.packExternalModules),
221+
'webpack:package:packExternalModules': () => Promise.resolve().then(() => this.packExternalModules()),
225222

226-
'webpack:package:packageModules': () => BbPromise.bind(this).then(this.packageModules),
223+
'webpack:package:packageModules': () => Promise.resolve().then(() => this.packageModules()),
227224

228-
'webpack:package:copyExistingArtifacts': () => BbPromise.bind(this).then(this.copyExistingArtifacts),
225+
'webpack:package:copyExistingArtifacts': () => Promise.resolve().then(() => this.copyExistingArtifacts()),
229226

230227
'before:offline:start': () =>
231-
BbPromise.bind(this)
232-
.tap(() => {
228+
Promise.resolve()
229+
.then(() => {
233230
lib.webpack.isLocal = true;
234231
// --skip-build override
235232
if (this.options['skip-build'] === false) {
236233
this.skipCompile = true;
237234
}
238235
})
239-
.then(this.prepareOfflineInvoke)
240-
.then(() => (this.skipCompile ? BbPromise.resolve() : this.wpwatch())),
236+
.then(() => this.prepareOfflineInvoke())
237+
.then(() => (this.skipCompile ? undefined : this.wpwatch())),
241238

242239
'before:offline:start:init': () =>
243-
BbPromise.bind(this)
244-
.tap(() => {
240+
Promise.resolve()
241+
.then(() => {
245242
lib.webpack.isLocal = true;
246243
// --skip-build override
247244
if (this.options['skip-build'] === false) {
248245
this.skipCompile = true;
249246
}
250247
})
251-
.then(this.prepareOfflineInvoke)
252-
.then(() => (this.skipCompile ? BbPromise.resolve() : this.wpwatch())),
248+
.then(() => this.prepareOfflineInvoke())
249+
.then(() => (this.skipCompile ? undefined : this.wpwatch())),
253250

254251
'before:step-functions-offline:start': () =>
255-
BbPromise.bind(this)
256-
.tap(() => {
252+
Promise.resolve()
253+
.then(() => {
257254
lib.webpack.isLocal = true;
258255
})
259-
.then(this.prepareStepOfflineInvoke)
256+
.then(() => this.prepareStepOfflineInvoke())
260257
.then(() => this.serverless.pluginManager.spawn('webpack:compile'))
261258
};
262259
}

lib/cleanup.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
const _ = require('lodash');
2-
const BbPromise = require('bluebird');
32
const fse = require('fs-extra');
43

54
module.exports = {
@@ -40,6 +39,6 @@ module.exports = {
4039
}
4140
}
4241

43-
return BbPromise.resolve();
42+
return Promise.resolve();
4443
}
4544
};

lib/compile.js

Lines changed: 78 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
const _ = require('lodash');
2-
const BbPromise = require('bluebird');
32
const webpack = require('webpack');
43
const { isBuiltin } = require('node:module');
54
const logStats = require('./logStats');
@@ -104,61 +103,84 @@ function getExternalModules({ compilation }) {
104103
return Array.from(externals);
105104
}
106105

107-
function webpackCompile(config, logStats) {
108-
return BbPromise.fromCallback(cb => webpack(config).run(cb)).then(stats => {
109-
// ensure stats in any array in the case of concurrent build.
110-
stats = stats.stats ? stats.stats : [stats];
106+
async function webpackCompile(config, logStats) {
107+
let stats = await new Promise((resolve, reject) => {
108+
webpack(config).run((error, result) => {
109+
if (error) {
110+
reject(error);
111+
return;
112+
}
113+
resolve(result);
114+
});
115+
});
111116

112-
_.forEach(stats, logStats);
117+
// ensure stats in any array in the case of concurrent build.
118+
stats = stats.stats ? stats.stats : [stats];
113119

114-
return _.map(stats, compileStats => ({
115-
outputPath: compileStats.compilation.compiler.outputPath,
116-
externalModules: getExternalModules(compileStats)
117-
}));
118-
});
120+
_.forEach(stats, logStats);
121+
122+
return _.map(stats, compileStats => ({
123+
outputPath: compileStats.compilation.compiler.outputPath,
124+
externalModules: getExternalModules(compileStats)
125+
}));
126+
}
127+
128+
async function mapWithConcurrency(items, concurrency, iteratee) {
129+
const results = new Array(items.length);
130+
let currentIndex = 0;
131+
132+
async function worker() {
133+
while (currentIndex < items.length) {
134+
const index = currentIndex;
135+
currentIndex += 1;
136+
results[index] = await iteratee(items[index], index);
137+
}
138+
}
139+
140+
const workerCount = Math.min(concurrency, items.length);
141+
await Promise.all(Array.from({ length: workerCount }, () => worker()));
142+
return results;
119143
}
120144

121-
function webpackConcurrentCompile(configs, logStats, concurrency, ServerlessError) {
145+
async function webpackConcurrentCompile(configs, logStats, concurrency, ServerlessError) {
122146
const errors = [];
123-
return BbPromise.map(
124-
configs,
125-
config => {
126-
if (isIndividialPackaging.call(this) && _.get(config, 'cache.type') === 'filesystem') {
127-
const clonedConfig = _.clone(config);
128-
const entryFunc = _.find(this.entryFunctions, ['entry.key', _.keys(config.entry)[0]]);
129-
clonedConfig.cache.name = entryFunc.func.name;
130-
return webpackCompile(clonedConfig, logStats, ServerlessError).catch(error => {
131-
errors.push(error);
132-
return error.stats;
133-
});
134-
}
135-
return webpackCompile(config, logStats, ServerlessError).catch(error => {
147+
148+
const stats = await mapWithConcurrency(configs, concurrency, async config => {
149+
if (isIndividialPackaging.call(this) && _.get(config, 'cache.type') === 'filesystem') {
150+
const clonedConfig = _.clone(config);
151+
const entryFunc = _.find(this.entryFunctions, ['entry.key', _.keys(config.entry)[0]]);
152+
clonedConfig.cache.name = entryFunc.func.name;
153+
return webpackCompile(clonedConfig, logStats, ServerlessError).catch(error => {
136154
errors.push(error);
137155
return error.stats;
138156
});
139-
},
140-
{ concurrency }
141-
).then(stats => {
142-
if (errors.length) {
143-
if (!this.log) {
144-
if (errors.length === 1) {
145-
throw errors[0];
146-
}
147-
throw new ServerlessError('Webpack compilation errors, see stats above');
148-
}
149-
throw new ServerlessError(
150-
`Webpack compilation failed:\n\n${_.join(
151-
_.map(errors, error => error.message),
152-
'\n\n'
153-
)}`
154-
);
155157
}
156-
return _.flatten(stats);
158+
return webpackCompile(config, logStats, ServerlessError).catch(error => {
159+
errors.push(error);
160+
return error.stats;
161+
});
157162
});
163+
164+
if (errors.length) {
165+
if (!this.log) {
166+
if (errors.length === 1) {
167+
throw errors[0];
168+
}
169+
throw new ServerlessError('Webpack compilation errors, see stats above');
170+
}
171+
throw new ServerlessError(
172+
`Webpack compilation failed:\n\n${_.join(
173+
_.map(errors, error => error.message),
174+
'\n\n'
175+
)}`
176+
);
177+
}
178+
179+
return _.flatten(stats);
158180
}
159181

160182
module.exports = {
161-
compile() {
183+
async compile() {
162184
if (this.log) {
163185
this.log.verbose('[Webpack] Building with Webpack');
164186
this.progress.get('webpack').update('[Webpack] Building with Webpack');
@@ -168,7 +190,7 @@ module.exports = {
168190

169191
const configs = ensureArray(this.webpackConfig);
170192
if (configs[0] === undefined) {
171-
return BbPromise.reject('Unable to find Webpack configuration');
193+
throw new this.serverless.classes.Error('Unable to find Webpack configuration');
172194
}
173195

174196
const logStats = getStatsLogger(configs[0].stats, this.serverless.cli.consoleLog, {
@@ -177,20 +199,21 @@ module.exports = {
177199
});
178200

179201
if (!this.configuration) {
180-
return BbPromise.reject(new this.serverless.classes.Error('Missing plugin configuration'));
202+
throw new this.serverless.classes.Error('Missing plugin configuration');
181203
}
182204
const concurrency = this.configuration.concurrency;
183205

184-
return webpackConcurrentCompile
185-
.call(this, configs, logStats, concurrency, this.serverless.classes.Error)
186-
.then(stats => {
187-
this.compileStats = { stats };
188-
189-
if (this.log) {
190-
this.progress.get('webpack').remove();
191-
}
206+
const stats = await webpackConcurrentCompile.call(
207+
this,
208+
configs,
209+
logStats,
210+
concurrency,
211+
this.serverless.classes.Error
212+
);
213+
this.compileStats = { stats };
192214

193-
return BbPromise.resolve();
194-
});
215+
if (this.log) {
216+
this.progress.get('webpack').remove();
217+
}
195218
}
196219
};

0 commit comments

Comments
 (0)