Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support webpack-dev-server v4 #17918

Merged
merged 6 commits into from
Aug 30, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion npm/angular/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"tslib": "^2.2.0",
"tslint": "5.20.1",
"typescript": "4.2.4",
"webpack-dev-server": "3.11.2",
"webpack-dev-server": "4.0.0",
"zone.js": "0.11.4"
},
"peerDependencies": {
Expand Down
7 changes: 4 additions & 3 deletions npm/webpack-dev-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"scripts": {
"build": "tsc",
"build-prod": "tsc",
"test": "tsc && mocha -r @packages/ts/register test/**/*.spec.ts test/*.spec.ts --exit",
"test": "node ./test-wds-3.js",
"test-all": "tsc && mocha -r @packages/ts/register test/**/*.spec.ts test/*.spec.ts --exit",
"watch": "tsc -w"
},
"dependencies": {
Expand All @@ -16,15 +17,15 @@
},
"devDependencies": {
"@types/webpack": ">=4",
"@types/webpack-dev-server": "^3.11.1",
"@types/webpack-dev-server": "^4.0.0",
"chai": "^4.2.0",
"html-webpack-plugin": "4.x",
"mocha": "^8.1.3",
"snap-shot-it": "7.9.3",
"speed-measure-webpack-plugin": "1.4.2",
"typescript": "^4.2.3",
"webpack": "^4.44.2",
"webpack-dev-server": "^3.11.0"
"webpack-dev-server": "^4.0.0"
},
"peerDependencies": {
"html-webpack-plugin": ">=4",
Expand Down
36 changes: 26 additions & 10 deletions npm/webpack-dev-server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { debug as debugFn } from 'debug'
import { AddressInfo } from 'net'
import { Server } from 'http'
import { start as createDevServer, StartDevServer } from './startServer'
import { webpackDevServerFacts } from './webpackDevServerFacts'

const debug = debugFn('cypress:webpack-dev-server:webpack')

Expand All @@ -17,26 +18,41 @@ export { StartDevServer }
export async function startDevServer (startDevServerArgs: StartDevServer, exitProcess = process.exit) {
const webpackDevServer = await createDevServer(startDevServerArgs, exitProcess)

return new Promise<ResolvedDevServerConfig>((resolve) => {
const httpSvr = webpackDevServer.listen(0, '127.0.0.1', () => {
// webpack-dev-server v3 returns `http.Server`.
// v4 returns a Promise that resolves `http.Server`.
// use Promise.resolve to make sure we get the `http.Server`,
// regardless of webpack-dev-server version.
Promise.resolve(httpSvr).then((server: Server) => {
return new Promise<ResolvedDevServerConfig>(async (resolve, reject) => {
if (webpackDevServerFacts.isV3()) {
const server: Server = webpackDevServer.listen(0, '127.0.0.1', () => {
// FIXME: handle address returning a string
const port = (server.address() as AddressInfo).port

debug('Component testing webpack server started on port', port)

return resolve({
resolve({
port,
close: (done?: DoneCallback) => {
httpSvr.close()
server.close()
done?.()
},
})
})
})

return
}

if (webpackDevServerFacts.isV4()) {
await webpackDevServer.start()

resolve({
// @ts-expect-error @types do not yet support v4
port: webpackDevServer.options.port,
close: (done?: DoneCallback) => {
webpackDevServer.stop()
done?.()
},
})

return
}

reject(webpackDevServerFacts.unsupported())
})
}
22 changes: 15 additions & 7 deletions npm/webpack-dev-server/src/startServer.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import Debug from 'debug'
import webpack from 'webpack'
import WebpackDevServer from 'webpack-dev-server'
import webpackDevServerPkg from 'webpack-dev-server/package.json'
import { makeWebpackConfig, UserWebpackDevServerOptions } from './makeWebpackConfig'
import { webpackDevServerFacts } from './webpackDevServerFacts'

export interface StartDevServer extends UserWebpackDevServerOptions {
/* this is the Cypress options object */
Expand Down Expand Up @@ -53,25 +53,33 @@ export async function start ({ webpackConfig: userWebpackConfig, template, optio
hot: false,
}

if (webpackDevServerPkg.version.match(/3\./)) {
if (webpackDevServerFacts.isV3()) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A debug message would be nice to print the version of WDS being used.

webpackDevServerConfig = {
...webpackDevServerConfig,
// @ts-expect-error ignore webpack-dev-server v3 type errors
inline: false,
publicPath: devServerPublicPathRoute,
noInfo: false,
}
} else if (webpackDevServerPkg.version.match(/4\./)) {

// @ts-expect-error ignore webpack-dev-server v3 type errors
return new WebpackDevServer(compiler, webpackDevServerConfig)
}

if (webpackDevServerFacts.isV4()) {
webpackDevServerConfig = {
host: 'localhost',
port: 'auto',
...userWebpackConfig?.devServer,
devMiddleware: {
publicPath: devServerPublicPathRoute,
},
hot: false,
}
} else {
throw Error(`@cypress/webpack-dev-server only supports webpack-dev-server v3 and v4. Found: ${webpackDevServerPkg.version}.`)

// @ts-expect-error Webpack types are clashing between Webpack and WebpackDevServer
return new WebpackDevServer(webpackDevServerConfig, compiler)
}

// @ts-ignore types for webpack v5 are incorrect?
return new WebpackDevServer(compiler, webpackDevServerConfig)
throw webpackDevServerFacts.unsupported()
}
14 changes: 14 additions & 0 deletions npm/webpack-dev-server/src/webpackDevServerFacts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import webpackDevServerPkg from 'webpack-dev-server/package.json'

export const webpackDevServerFacts = {
version: webpackDevServerPkg.version,
isV3 (version = webpackDevServerPkg.version) {
return /^3\./.test(version)
},
isV4 (version = webpackDevServerPkg.version) {
return /^4\./.test(version)
},
unsupported () {
return Error(`@cypress/webpack-dev-server only supports webpack-dev-server v3 and v4. Found: ${webpackDevServerFacts.version}.`)
},
}
49 changes: 49 additions & 0 deletions npm/webpack-dev-server/test-wds-3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const execa = require('execa')
const pkg = require('./package.json')
const fs = require('fs')

/**
* This file installs WebpackDevServer 3 and runs the tests for the dev-server.
* We read package.json, update the webpack version, then re-run yarn install.
* After it finishes, pass or fail,
* we revert the package.json back to the original state.
*
* The tests for the example projects (inside of examples) run with WebpackDevServer 3.
* This ensures we have some coverage for both versions.
*/
const main = async () => {
const originalPkg = JSON.stringify(pkg, null, 2)

const resetPkg = async () => {
fs.writeFileSync('package.json', originalPkg, 'utf8')
await execa('yarn', ['install'], { stdio: 'inherit' })
}

const checkExit = async ({ exitCode }) => {
if (typeof exitCode !== 'number') {
// eslint-disable-next-line no-console
console.error(`Finished with missing exit code from execa (received ${exitCode})`)
}

await resetPkg()
process.exit(exitCode)
}

pkg.devDependencies['webpack-dev-server'] = '^3.11.0'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, should we specify the exact version during CI runs to ensure the tests always us the same one? eg 3.11.0 (no ^)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense I'll pin it.

// eslint-disable-next-line no-console
console.log('[@cypress/webpack-dev-server]: updating package.json...')
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2))

// eslint-disable-next-line no-console
console.log('[@cypress/webpack-dev-server]: install dependencies...')
await execa('yarn', ['install'], { stdio: 'inherit' })

const { exitCode } = await execa('yarn', ['test-all'], { stdio: 'inherit' })

await checkExit({ exitCode })
}

// execute main function if called from command line
if (require.main === module) {
main()
}
12 changes: 6 additions & 6 deletions npm/webpack-dev-server/test/e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import webpack from 'webpack'
import path from 'path'
import sinon from 'sinon'
import { expect } from 'chai'
import { EventEmitter } from 'events'
import http from 'http'
import fs from 'fs'
import { webpackDevServerFacts } from '../src/webpackDevServerFacts'

import { startDevServer } from '../'

Expand Down Expand Up @@ -34,11 +34,11 @@ const requestSpecFile = (port: number) => {

const root = path.join(__dirname, '..')

const webpackConfig: webpack.Configuration = {
output: {
path: root,
publicPath: root,
},
const webpackConfig = {
devServer: webpackDevServerFacts.isV3()
? { contentBase: root }
: { static: { directory: root } },

}

const specs: Cypress.Cypress['spec'][] = [
Expand Down
19 changes: 19 additions & 0 deletions npm/webpack-dev-server/test/unit/webpackDevServerFacts.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { expect } from 'chai'
import { webpackDevServerFacts } from '../../src/webpackDevServerFacts'

describe('webpackDevServerFacts', () => {
it('should detect v3', () => {
expect(webpackDevServerFacts.isV3('3.0.0')).equals(true)
expect(webpackDevServerFacts.isV3('3.1.4')).equals(true)
expect(webpackDevServerFacts.isV3('4.0.0')).equals(false)
expect(webpackDevServerFacts.isV3('4.3.0')).equals(false)
})

it('should detect v4', () => {
expect(webpackDevServerFacts.isV4('3.0.0')).equals(false)
expect(webpackDevServerFacts.isV4('3.1.4')).equals(false)
expect(webpackDevServerFacts.isV4('3.4.4')).equals(false)
expect(webpackDevServerFacts.isV4('4.0.0')).equals(true)
expect(webpackDevServerFacts.isV4('4.3.0')).equals(true)
})
})
Loading