Skip to content
This repository was archived by the owner on Oct 1, 2020. It is now read-only.

Commit 49b4f48

Browse files
committed
patch: improve lazy-loading of babel deps and add tests
1 parent fe6f5b8 commit 49b4f48

File tree

4 files changed

+89
-45
lines changed

4 files changed

+89
-45
lines changed

index.js

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,35 @@
1-
const cloneDeep = require('lodash.clonedeep')
21
const path = require('path')
32
const webpack = require('webpack')
43
const debug = require('debug')('cypress:webpack')
54

65
const createDeferred = require('./deferred')
6+
const stubbableRequire = require('./stubbable-require')
77

88
const bundles = {}
99

10-
// by default, we transform JavaScript supported by @babel/preset-env
11-
const defaultBabelLoaderRules = () => {
12-
return [
13-
{
14-
test: /\.js?$/,
15-
exclude: [/node_modules/],
16-
use: [
17-
{
18-
loader: require.resolve('babel-loader'),
19-
options: {
20-
presets: [require.resolve('@babel/preset-env')],
21-
},
22-
},
23-
],
24-
},
25-
]
26-
}
27-
2810
// we don't automatically load the rules, so that the babel dependencies are
2911
// not required if a user passes in their own configuration
30-
const defaultOptions = {
31-
webpackOptions: {
12+
const getDefaultWebpackOptions = () => {
13+
debug('load default options')
14+
15+
return {
3216
module: {
33-
rules: [],
17+
rules: [
18+
{
19+
test: /\.jsx?$/,
20+
exclude: [/node_modules/],
21+
use: [
22+
{
23+
loader: stubbableRequire.resolve('babel-loader'),
24+
options: {
25+
presets: [stubbableRequire.resolve('@babel/preset-env')],
26+
},
27+
},
28+
],
29+
},
30+
],
3431
},
35-
},
36-
watchOptions: {},
32+
}
3733
}
3834

3935
// export a function that returns another function, making it easy for users
@@ -57,24 +53,24 @@ const preprocessor = (options = {}) => {
5753
// the supported file and spec file to be requested again
5854
return (file) => {
5955
const filePath = file.filePath
56+
6057
debug('get', filePath)
6158

6259
// since this function can get called multiple times with the same
6360
// filePath, we return the cached bundle promise if we already have one
6461
// since we don't want or need to re-initiate webpack for it
6562
if (bundles[filePath]) {
6663
debug(`already have bundle for ${filePath}`)
64+
6765
return bundles[filePath]
6866
}
6967

7068
// user can override the default options
71-
let webpackOptions = Object.assign({}, defaultOptions.webpackOptions, options.webpackOptions)
72-
// here is where we load the default rules if the user has not passed
73-
// in their own configuration
74-
if (webpackOptions.module.rules === defaultOptions.webpackOptions) {
75-
webpackOptions.module.rules = defaultBabelLoaderRules()
76-
}
77-
let watchOptions = Object.assign({}, defaultOptions.watchOptions, options.watchOptions)
69+
let webpackOptions = options.webpackOptions || getDefaultWebpackOptions()
70+
const watchOptions = options.watchOptions || {}
71+
72+
debug('webpackOptions: %o', webpackOptions)
73+
debug('watchOptions: %o', watchOptions)
7874

7975
// we're provided a default output path that lives alongside Cypress's
8076
// app data files so we don't have to worry about where to put the bundled
@@ -186,14 +182,16 @@ const preprocessor = (options = {}) => {
186182
}
187183
}
188184

189-
// provide a clone of the default options, making sure to lazy-load
190-
// babel dependencies so that they aren't required unless the user
191-
// utilizes them
185+
// provide a clone of the default options, lazy-loading them
186+
// so they aren't required unless the user utilizes them
192187
Object.defineProperty(preprocessor, 'defaultOptions', {
193188
get () {
194-
const clonedDefaults = cloneDeep(defaultOptions)
195-
clonedDefaults.webpackOptions.module.rules = defaultBabelLoaderRules()
196-
return clonedDefaults
189+
debug('get default options')
190+
191+
return {
192+
webpackOptions: getDefaultWebpackOptions(),
193+
watchOptions: {},
194+
}
197195
},
198196
})
199197

package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"secure": "nsp check",
3030
"size": "t=\"$(npm pack .)\"; wc -c \"${t}\"; tar tvf \"${t}\"; rm \"${t}\";",
3131
"test": "mocha",
32-
"test-watch": "chokidar '*.js' 'test/*.js' -c 'npm test'",
32+
"test-watch": "chokidar '*.js' 'test/*.js' -c 'mocha'",
3333
"semantic-release": "semantic-release pre && npm publish --access public && semantic-release post"
3434
},
3535
"devDependencies": {
@@ -68,8 +68,7 @@
6868
},
6969
"dependencies": {
7070
"bluebird": "3.5.0",
71-
"debug": "3.1.0",
72-
"lodash.clonedeep": "4.5.0"
71+
"debug": "3.1.0"
7372
},
7473
"release": {
7574
"verifyConditions": "condition-circle",

stubbable-require.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
resolve (dependency) {
3+
return require.resolve(dependency)
4+
},
5+
}

test/index_spec.js

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ mockery.enable({
1515
mockery.registerMock('webpack', webpack)
1616

1717
const preprocessor = require('../index')
18+
const stubbableRequire = require('../stubbable-require')
1819

1920
describe('webpack preprocessor', function () {
2021
beforeEach(function () {
@@ -43,15 +44,14 @@ describe('webpack preprocessor', function () {
4344
on: sandbox.stub(),
4445
emit: sandbox.spy(),
4546
}
46-
this.options = {}
4747
this.util = {
4848
getOutputPath: sandbox.stub().returns(this.outputPath),
4949
fileUpdated: sandbox.spy(),
5050
onClose: sandbox.stub(),
5151
}
5252

53-
this.run = () => {
54-
return preprocessor(this.options)(this.file)
53+
this.run = (options, file = this.file) => {
54+
return preprocessor(options)(file)
5555
}
5656
})
5757

@@ -128,8 +128,9 @@ describe('webpack preprocessor', function () {
128128
it('includes watchOptions if provided', function () {
129129
this.file.shouldWatch = true
130130
this.compilerApi.watch.yields(null, this.statsApi)
131-
this.options.watchOptions = { poll: true }
132-
return this.run().then(() => {
131+
const options = { watchOptions: { poll: true } }
132+
133+
return this.run(options).then(() => {
133134
expect(this.compilerApi.watch.lastCall.args[0]).to.eql({
134135
poll: true,
135136
})
@@ -174,6 +175,47 @@ describe('webpack preprocessor', function () {
174175
expect(this.watchApi.close).not.to.be.called
175176
})
176177
})
178+
179+
it('uses default webpack options when no user options', function () {
180+
return this.run().then(() => {
181+
expect(webpack.lastCall.args[0].module.rules[0].use).to.have.length(1)
182+
expect(webpack.lastCall.args[0].module.rules[0].use[0].loader).to.be.a('string')
183+
})
184+
})
185+
186+
it('uses default options when no user webpack options', function () {
187+
return this.run({}).then(() => {
188+
expect(webpack.lastCall.args[0].module.rules[0].use).to.have.length(1)
189+
expect(webpack.lastCall.args[0].module.rules[0].use[0].loader).to.be.a('string')
190+
})
191+
})
192+
193+
it('does not use default options when user options are non-default', function () {
194+
const options = { webpackOptions: { module: { rules: [] } } }
195+
196+
return this.run(options).then(() => {
197+
expect(webpack.lastCall.args[0].module).to.equal(options.webpackOptions.module)
198+
})
199+
})
200+
201+
it('requires babel dependencies when default options are used', function () {
202+
sandbox.spy(stubbableRequire, 'resolve')
203+
204+
return this.run().then(() => {
205+
expect(stubbableRequire.resolve).to.be.calledWith('babel-loader')
206+
expect(stubbableRequire.resolve).to.be.calledWith('@babel/preset-env')
207+
})
208+
})
209+
210+
it('does not requires babel dependencies when user options are non-default', function () {
211+
sandbox.spy(stubbableRequire, 'resolve')
212+
const options = { webpackOptions: { module: { rules: [] } } }
213+
214+
return this.run(options).then(() => {
215+
expect(stubbableRequire.resolve).not.to.be.calledWith('babel-loader')
216+
expect(stubbableRequire.resolve).not.to.be.calledWith('@babel/preset-env')
217+
})
218+
})
177219
})
178220

179221
describe('when it errors', function () {

0 commit comments

Comments
 (0)