chore!: drop webpack-4 support in v5 (#6598)

1. I don't think I'll ever have the capacity to keep maintaining this
compat plugin. It's better to drop it now than later.
2. The plugin is needed at the time of alpha.0 because many ecosystem
plugins does not support webpack 5. But now I don't think it will be a
major hurdle.
3. The implementation was too hacky.
This commit is contained in:
Haoqun Jiang
2021-07-30 14:03:54 +08:00
committed by GitHub
parent 45e804ba50
commit e41ef41540
12 changed files with 2 additions and 398 deletions

View File

@@ -49,13 +49,6 @@ jobs:
at: ~/
- run: yarn test -p cli,cli-service,cli-shared-utils
core-webpack-4:
<<: *defaults
steps:
- attach_workspace:
at: ~/
- run: VUE_CLI_USE_WEBPACK4=true yarn test -p cli,cli-service,cli-shared-utils
typescript:
<<: *defaults
steps:
@@ -63,13 +56,6 @@ jobs:
at: ~/
- run: yarn test 'ts(?:\w(?!E2e))+\.spec\.js$'
typescript-webpack-4:
<<: *defaults
steps:
- attach_workspace:
at: ~/
- run: VUE_CLI_USE_WEBPACK4=true yarn test 'ts(?:\w(?!E2e))+\.spec\.js$'
plugins:
<<: *defaults
steps:
@@ -79,13 +65,6 @@ jobs:
- run: yarn check-links
- run: yarn test -p eslint,pwa,babel,babel-preset-app,vuex,router
plugins-webpack-4:
<<: *defaults
steps:
- attach_workspace:
at: ~/
- run: VUE_CLI_USE_WEBPACK4=true yarn test -p eslint,pwa,babel,babel-preset-app,vuex,router
tests:
<<: *defaults
steps:
@@ -95,14 +74,6 @@ jobs:
# e2e-nightwatch was left out due to some unknown issues with selenium and the CI image
- run: yarn test tsPluginE2e
tests-webpack-4:
<<: *defaults
steps:
- attach_workspace:
at: ~/
- run: VUE_CLI_USE_WEBPACK4=true yarn test -p unit-mocha,unit-jest,e2e-cypress
- run: VUE_CLI_USE_WEBPACK4=true yarn test tsPluginE2e
cli-ui:
<<: *defaults
steps:
@@ -116,8 +87,6 @@ jobs:
- store_artifacts:
path: /home/circleci/.npm/_logs
# TODO: cli-ui-webpack-4
workflows:
version: 2
test:
@@ -128,34 +97,18 @@ workflows:
<<: *filters
requires:
- install
- core-webpack-4:
<<: *filters
requires:
- install
- typescript:
<<: *filters
requires:
- install
- typescript-webpack-4:
<<: *filters
requires:
- install
- plugins:
<<: *filters
requires:
- install
- plugins-webpack-4:
<<: *filters
requires:
- install
- tests:
<<: *filters
requires:
- install
- tests-webpack-4:
<<: *filters
requires:
- install
- cli-ui:
<<: *filters
requires:

View File

@@ -1,3 +0,0 @@
# @vue/cli-plugin-webpack-4
This plugin provides compatibily for webpack 4 in Vue CLI 5.

View File

@@ -60,22 +60,6 @@ Besides the internal changes that are only noticeable for custom configurations,
1. Named exports from JSON modules are no longer supported. Instead of `import { version } from './package.json'; console.log(version);` use `import package from './package.json'; console.log(package.version);`
2. Webpack 5 does no longer include polyfills for Node.js modules by default. You shall see an informative error message if your code relies on any of these modules. A detailed list of previously polyfilled modules is also available [here](https://github.com/webpack/webpack/pull/8460/commits/a68426e9255edcce7822480b78416837617ab065).
#### Opt Out to Webpack 4
Considering many ecosystem packages haven't catched up yet, we provided a plugin to opt out to webpack 4 for easier migration.
It's as simple as running
```sh
vue add webpack-4
```
at the project root.
Underlyingly, it uses the [`resolutions`](https://classic.yarnpkg.com/en/docs/selective-version-resolutions) field for Yarn and PNPM users, and [`module-alias`](https://github.com/ilearnio/module-alias) for NPM users.
Though both work in all our tests, please be aware that the `module-alias` approach is still considered hacky, and may not be as stable as the `"resolutions"` one.
#### Changes to the `build` command and modern mode
Starting with v5.0.0-beta.0, running `vue-cli-service build` will automatically generate different bundles based on your browserslist configurations.

View File

@@ -7,10 +7,3 @@ module.exports = {
'**/__tests__/**/*.spec.js'
]
}
if (process.env.VUE_CLI_USE_WEBPACK4) {
module.exports.moduleNameMapper = {
'^webpack$': 'webpack-4',
'^webpack/(.*)': 'webpack-4/$1'
}
}

View File

@@ -1,3 +0,0 @@
# @vue/cli-plugin-webpack-4
This plugin provides compatibily for webpack 4 in Vue CLI 5.

View File

@@ -1,51 +0,0 @@
const { semver } = require('@vue/cli-shared-utils')
/** @type {import('@vue/cli').GeneratorPlugin} */
module.exports = (api) => {
api.extendPackage({
devDependencies: {
webpack: '^4.0.0'
},
// Force resolutions is more reliable than module-alias
// Yarn and PNPM 5.10+ support this feature
// So we'll try to use that whenever possible
resolutions: {
'@vue/cli-*/webpack': '^4.0.0',
'html-webpack-plugin': '^4.5.1'
}
})
api.extendPackage(
(pkg) => {
const oldDevDeps = pkg.devDependencies
const newDevDeps = {}
const unsupportedRanges = {
'less-loader': '>= 8.0.0',
'sass-loader': '>= 11.0.0',
'stylus-loader': '>= 5.0.0'
}
const maxSupportedRanges = {
'less-loader': '^7.3.0',
'sass-loader': '^10.1.1',
'stylus-loader': '^4.3.3'
}
for (const loader of ['less-loader', 'sass-loader', 'stylus-loader']) {
if (
oldDevDeps[loader] &&
semver.intersects(oldDevDeps[loader], unsupportedRanges[loader])
) {
newDevDeps[loader] = maxSupportedRanges[loader]
}
}
const toMerge = { devDependencies: newDevDeps }
return toMerge
},
{
warnIncompatibleVersions: false,
forceOverwrite: true
}
)
}

View File

@@ -1,158 +0,0 @@
const fs = require('fs')
const path = require('path')
const moduleAlias = require('module-alias')
const htmlWebpackPlugin4Path = path.dirname(require.resolve('html-webpack-plugin/package.json'))
// We have to use module-alias for html-webpack-plguin, as it is required by many other plugins
// as peer dependency for its `getHooks` API.
// Should add the alias as early as possible to avoid problems
// TODO: add debugging log here
moduleAlias.addAlias('html-webpack-plugin', htmlWebpackPlugin4Path)
/** @type {import('@vue/cli-service').ServicePlugin} */
module.exports = (api, rootOptions) => {
api.chainWebpack(config => {
// webpack-4 alias is set for the webpack-dev-server
// should also set for the injected client hmr code so as to avoid mismatch
const webpack4Path = path.dirname(require.resolve('webpack/package.json'))
config.resolve.alias.set('webpack', webpack4Path)
// Node.js polyfills
// They are not polyfilled by default in webpack 5
// <https://github.com/webpack/webpack/pull/8460>
// In webpack 4, we used to disabled many of the core module polyfills too
config.node
.merge({
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// process is injected via DefinePlugin, although some 3rd party
// libraries may require a mock to work properly (#934)
process: 'mock',
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
})
// Yarn PnP / Yarn 2 support
config.resolve
.plugin('pnp')
.use({ ...require('pnp-webpack-plugin') })
.end()
config.resolveLoader
.plugin('pnp-loaders')
.use({ ...require('pnp-webpack-plugin').topLevelLoader })
.end()
// Use postcss-loader v7
const shadowMode = !!process.env.VUE_CLI_CSS_SHADOW_MODE
const isProd = process.env.NODE_ENV === 'production'
const { extract = isProd } = rootOptions.css || {}
const shouldExtract = extract !== false && !shadowMode
const needInlineMinification = isProd && !shouldExtract
const postcssLoaderPath = require.resolve('postcss-loader')
const langs = ['css', 'postcss', 'scss', 'sass', 'less', 'stylus']
const matches = ['vue-modules', 'vue', 'normal-modules', 'normal']
langs.forEach(lang =>
matches.forEach(match => {
const rule = config.module
.rule(lang)
.oneOf(match)
if (needInlineMinification) {
rule.use('cssnano').loader(postcssLoaderPath)
}
rule.use('postcss-loader').loader(postcssLoaderPath)
})
)
if (!process.env.VUE_CLI_BUILD_TARGET || process.env.VUE_CLI_BUILD_TARGET === 'app') {
const isLegacyBundle = process.env.VUE_CLI_MODERN_MODE && !process.env.VUE_CLI_MODERN_BUILD
const publicDir = api.resolve('public')
if (!isLegacyBundle && fs.existsSync(publicDir)) {
const CopyWebpackPluginV6 = require('copy-webpack-plugin')
config
.plugin('copy')
.init((Plugin, args) => new CopyWebpackPluginV6(...args))
}
if (process.env.NODE_ENV === 'production') {
// In webpack 5, optimization.chunkIds is set to `deterministic` by default in production
// In webpack 4, we use the following trick to keep chunk ids stable so async chunks have consistent hash (#1916)
config
.plugin('named-chunks')
.use(require('webpack').NamedChunksPlugin, [chunk => {
if (chunk.name) {
return chunk.name
}
const hash = require('hash-sum')
const joinedHash = hash(
Array.from(chunk.modulesIterable, m => m.id).join('_')
)
return `chunk-` + joinedHash
}])
}
if (process.env.NODE_ENV !== 'test') {
config.optimization.splitChunks({
cacheGroups: {
vendors: {
name: `chunk-vendors`,
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: 'initial'
},
common: {
name: `chunk-common`,
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true
}
}
})
}
}
if (process.env.NODE_ENV === 'production') {
const TerserPluginV4 = require('terser-webpack-plugin')
config.optimization.minimizer('terser').init(
(Plugin, [terserPluginOptions]) =>
new TerserPluginV4({
sourceMap: rootOptions.productionSourceMap,
cache: true,
...terserPluginOptions
})
)
if (shouldExtract) {
const CssMinimizerPluginV1 = require('css-minimizer-webpack-plugin')
config.optimization.minimizer('css').init(
(Plugin, [cssMinimizerOptions]) =>
new CssMinimizerPluginV1({
sourceMap: rootOptions.productionSourceMap,
...cssMinimizerOptions
})
)
}
// DeterministicModuleIdsPlugin is only available in webpack 5
// (and enabled by default in production mode).
// In webpack 4, we need HashedModuleIdsPlugin
// to keep module.id stable when vendor modules does not change.
// It is "the second best solution for long term caching".
// <https://github.com/webpack/webpack/pull/7399#discussion_r193970769>
config.optimization.set('hashedModuleIds', true)
}
})
}

View File

@@ -1,41 +0,0 @@
{
"name": "@vue/cli-plugin-webpack-4",
"version": "5.0.0-beta.2",
"description": "webpack-4 plugin for @vue/cli v5",
"main": "index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/vuejs/vue-cli.git",
"directory": "packages/@vue/cli-plugin-webpack-4"
},
"keywords": [
"vue",
"cli",
"webpack 4"
],
"author": "Haoqun Jiang",
"license": "MIT",
"bugs": {
"url": "https://github.com/vuejs/vue-cli/issues"
},
"homepage": "https://github.com/vuejs/vue-cli/tree/dev/packages/@vue/@vue/cli-plugin-webpack-4#readme",
"publishConfig": {
"access": "public"
},
"dependencies": {
"@vue/cli-shared-utils": "^5.0.0-beta.2",
"copy-webpack-plugin": "^6.4.1",
"css-minimizer-webpack-plugin": "^1.2.0",
"hash-sum": "^2.0.0",
"html-webpack-plugin": "^4.5.1",
"module-alias": "^2.2.2",
"pnp-webpack-plugin": "^1.6.4",
"postcss": "^8.2.6",
"postcss-loader": "^4.2.0",
"terser-webpack-plugin": "^4.2.3",
"webpack": "^4.44.2"
},
"peerDependencies": {
"@vue/cli-service": "^5.0.0-0"
}
}

View File

@@ -9,7 +9,6 @@ const defaultsDeep = require('lodash.defaultsdeep')
const { warn, error, isPlugin, resolvePluginId, loadModule, resolvePkg, resolveModule, sortPlugins } = require('@vue/cli-shared-utils')
const { defaults } = require('./options')
const checkWebpack = require('./util/checkWebpack')
const loadFileConfig = require('./util/loadFileConfig')
const resolveUserConfig = require('./util/resolveUserConfig')
@@ -17,8 +16,6 @@ const resolveUserConfig = require('./util/resolveUserConfig')
const isPromise = p => p && typeof p.then === 'function'
module.exports = class Service {
constructor (context, { plugins, pkg, inlineOptions, useBuiltIn } = {}) {
checkWebpack(context)
process.VUE_CLI_SERVICE = this
this.initialized = false
this.context = context
@@ -199,17 +196,6 @@ module.exports = class Service {
}
})
// Add the plugin automatically to simplify the webpack-4 tests
// so that a simple Jest alias would suffice, avoid changing every
// preset used in the tests
if (
process.env.VUE_CLI_TEST &&
process.env.VUE_CLI_USE_WEBPACK4 &&
!projectPlugins.some((p) => p.id === '@vue/cli-plugin-webpack-4')
) {
builtInPlugins.push(idToPlugin('@vue/cli-plugin-webpack-4'))
}
plugins = builtInPlugins.concat(projectPlugins)
}

View File

@@ -1,55 +0,0 @@
const path = require('path')
const { warn, loadModule, resolveModule } = require('@vue/cli-shared-utils')
const moduleAlias = require('module-alias')
/**
* If the user has installed a version of webpack themself, load it.
* Otherwise, load the webpack that @vue/cli-service depends on.
* @param {string} cwd the user project root
* @returns {import('webpack')} note: the return type is for webpack 5 only
*/
module.exports = function checkWebpack (cwd) {
// Jest module alias can't affect sub-processes, so we have to alias it manually
if (
process.env.VUE_CLI_TEST &&
process.env.VUE_CLI_USE_WEBPACK4 &&
require('webpack/package.json').version[0] !== '4'
) {
const webpack4Path = path.dirname(require.resolve('webpack-4/package.json'))
moduleAlias.addAlias('webpack', webpack4Path)
return
}
// Check the package.json,
// and only load from the project if webpack is explictly depended on,
// in case of accidental hoisting.
let pkg = {}
try {
pkg = loadModule('./package.json', cwd)
} catch (e) {}
const deps = {
...pkg.dependencies,
...pkg.devDependencies,
...pkg.optionalDependencies
}
if (deps.webpack) {
const customWebpackVersion = loadModule('webpack/package.json', cwd).version
const requiredWebpackVersion = require('webpack/package.json').version
// A custom webpack version is found but no force resolutions used.
// So the webpack version in this package is still 5.x.
// This may cause problems for loaders/plugins required in this package.
// Because many uses runtime sniffing to run conditional code for different webpack versions.
if (customWebpackVersion !== requiredWebpackVersion) {
// TODO: recommend users to use yarn force resolutions or pnpm hooks instead
warn(`Using "module-alias" to load custom webpack version.`)
const webpack4Path = path.dirname(resolveModule('webpack/package.json', cwd))
moduleAlias.addAlias('webpack', webpack4Path)
}
}
}

View File

@@ -120,8 +120,7 @@
"vue": "^2.6.12",
"vue-router": "^3.5.1",
"vue-template-compiler": "^2.6.12",
"vuex": "^3.6.2",
"webpack-4": "npm:webpack@^4.44.2"
"vuex": "^3.6.2"
},
"publishConfig": {
"access": "public"

View File

@@ -10,7 +10,7 @@ if (args.p) {
rawArgs.splice(i, 2)
}
const e2ePathPattern = 'Migrator|Vue3|mochaPlugin|MochaPlugin|cli-plugin-webpack-4'
const e2ePathPattern = 'Migrator|Vue3|mochaPlugin|MochaPlugin'
if (args['e2e-only']) {
regex = e2ePathPattern