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

Commit df443e0

Browse files
committed
add comments to document code
1 parent ae856d0 commit df443e0

File tree

1 file changed

+48
-2
lines changed

1 file changed

+48
-2
lines changed

index.js

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const createDeferred = require('./deferred')
66

77
const bundles = {}
88

9+
// by default, we transform JavaScript (up to anything at stage-4) and JSX
910
const defaults = {
1011
webpackOptions: {
1112
module: {
@@ -29,22 +30,47 @@ const defaults = {
2930
watchOptions: {},
3031
}
3132

33+
// export a function that returns another function, making it easy for users
34+
// to configure like so:
35+
//
36+
// register('on:spec:file:preprocessor', webpack(config, userOptions))
37+
//
3238
module.exports = (config, userOptions = {}) => {
3339
if (!config || typeof config.isTextTerminal !== 'boolean') {
3440
throw new Error(`Cypress Webpack Preprocessor must be called with the Cypress config as its first argument. You passed: ${JSON.stringify(config, null, 2)}`)
3541
}
3642

3743
log('user options:', userOptions)
3844

45+
46+
// we return function that accepts the arguments provided by
47+
// the event 'on:spec:file:preprocessor'
48+
//
49+
// this function will get called for the support file when a project is loaded
50+
// (if the support file is not disabled)
51+
// it will also get calledfor a spec file when that spec is requested by
52+
// the Cypress runner
53+
//
54+
// when running in the GUI, it will likely get called multiple times
55+
// with the same filePath, as the user could re-run the tests, causing
56+
// the supported file and spec file to be requested again
3957
return (filePath, util) => {
4058
log('get', filePath)
4159

60+
// since this function can get called multiple times with the same
61+
// filePath, we return the cached bundle promise if we already have one
62+
// since we don't want or need to re-initiate webpack for it
4263
if (bundles[filePath]) {
4364
log(`already have bundle for ${filePath}`)
4465
return bundles[filePath]
4566
}
4667

68+
// if we're in a text terminal, this is a one-time run, probably in CI
69+
// so we don't need to watch
4770
const shouldWatch = !config.isTextTerminal
71+
// util.getOutputPath returns a path alongside Cypress's other app data
72+
// files so we don't have to worry about where to put the bundled
73+
// file on disk
4874
const outputPath = util.getOutputPath(filePath)
4975

5076
// user can override the default options
@@ -65,19 +91,28 @@ module.exports = (config, userOptions = {}) => {
6591

6692
const compiler = webpack(webpackOptions)
6793

94+
// we keep a reference to the latest bundle in this scope
95+
// it's a deferred object that will be resolved or rejected in
96+
// the `handle` function below and its promise is what is ultimately
97+
// returned from this function
6898
let latestBundle = createDeferred()
99+
// cache the bundle promise, so it can be returned if this function
100+
// is invoked again with the same filePath
69101
bundles[filePath] = latestBundle.promise
70102

103+
// this function is called when bundling is finished, once at the start
104+
// and, if watching, each time watching triggers a re-bundle
71105
const handle = (err, stats) => {
72106
if (err) {
73107
err.filePath = filePath
74-
//// backup the original stack before it's
75-
//// potentially modified from bluebird
108+
// backup the original stack before it's
109+
// potentially modified from bluebird
76110
err.originalStack = err.stack
77111
log(`errored bundling ${outputPath}`, err)
78112
return latestBundle.reject(err)
79113
}
80114

115+
// these stats are really only useful for debugging
81116
const jsonStats = stats.toJson()
82117
if (jsonStats.errors.length > 0) {
83118
log(`soft errors for ${outputPath}`)
@@ -89,14 +124,21 @@ module.exports = (config, userOptions = {}) => {
89124
}
90125

91126
log('finished bundling', outputPath)
127+
// resolve with the outputPath so Cypress knows where to serve
128+
// the file from
92129
latestBundle.resolve(outputPath)
93130
}
94131

132+
// this event is triggered when watching and a file is saved
95133
compiler.plugin('compile', () => {
96134
log('compile', filePath)
135+
// we overwrite the latest bundle, so that a new call to this function
136+
// returns a promise that resolves when the bundling is finished
97137
latestBundle = createDeferred()
98138
bundles[filePath] = latestBundle.promise.tap(() => {
99139
log('- compile finished for', filePath)
140+
// when the bundling is finished, we call `util.fileUpdated`
141+
// to let Cypress know to re-run the spec
100142
util.fileUpdated(filePath)
101143
})
102144
})
@@ -109,6 +151,8 @@ module.exports = (config, userOptions = {}) => {
109151
compiler.watch(watchOptions, handle) :
110152
compiler.run(handle)
111153

154+
// when the spec or project is closed, we need to clean up the cached
155+
// bundle promise and stop the watcher via `bundler.close()`
112156
util.onClose(() => {
113157
log('close', filePath)
114158
delete bundles[filePath]
@@ -118,6 +162,8 @@ module.exports = (config, userOptions = {}) => {
118162
}
119163
})
120164

165+
// return the promise, which will resolve with the outputPath or reject
166+
// with any error encountered
121167
return bundles[filePath]
122168
}
123169
}

0 commit comments

Comments
 (0)