如果你的事vue-cli 或者其他cli 关于IE 兼容不具有什么参考价值。如果是react 项目,你看看就行。
webpack3的打包速度已成为诟病,所以我们将原来的webpack3升级至webpack5
首先就是原来的项目结构,主要在于build目录下面,存在基础配置,开发配置,生产配置
build
|-------util.js
|-------webpack.common.js
|-------webpack.dev.js
|-------webpack.prod.conf.js
首先,卸载原有的webpack
npm install webpack webpack-dev-server webpack-cli
安装完成以后
npm install -g npm-check-updates
安装完成以后执行npm-check-updates,
修改 package.json 文件到相应的版本。
执行 npm cache clean -f , 删除node-modules 执行npm install,
此时会报各种版本不匹配,一定要降级,除了webpack 版本维持不动以外,其他版本尽量往下降
以上升级完成以后。除了IE 以外都可以正常运行了。
webpack 5.0 以后,IE 兼容参考babel-preset 官方文档。IE 的兼容一言难进,特别是webpack3,升级到webpack5.0以后,webpack3的兼容写法全部报废。
个人意见如下:
1. 使用core-js 如果你的代码有用到Map Set symbol 等新特性建议使用core-js3.0 如果没有用到core-js2.0
2. webpack3.0 一系列babel- 的插件, 除 babel-loader 以外。其他都要替换成@babel-开头的(版本不是越新越好core-js2 和core-js3 npm 版本库看发布日期,下载时候下年限差不多的就行。)
3. webapck 打包输出,output:[core-js,main.js] 网上还有其他方案, 个人兼容如果是core-js2.0.0 使用这个,如果是安装的是core-js3.0。可以尝试网上其他答案。
4. 插件注意 @babel/plugin-transform-runtime 是做promise 兼容处理的,内部core-js配置 和上一步core-js 版本没有任何关系。下载完成之后看node_modules 这个插件使用的是core-js 第几个版本 就在.babelrc 配置第几个。
5.IE兼容如果出错了,在IE 预览时,一般都会明确的指向node_modules 那个包,或者是你内部代码哪里写的又问题,一定要记住千万不要去改相关代码, babel-preset 官网找到相应插件解析, 如果node_modules 中的 包又问题,就降版本,降版本,降版本。
6. 第三方引入的静态文件,这一类的如果是,index.html 之间标签引入两个建议1.要么放到cdn 独立的加速服务器,要么统一放到本地的一个文件夹(static) 这个文件夹千万不要 使用babel-loader 再次解析,IE 会出现很多莫名的错误(这一点坑了我很久)
IE 浏览器兼容就是以上所述,如果其他大佬有补充请留言
代码文件有部分注释,可以关注一下也许对你有一定的帮助
文件如下 ----dll 打包具体怎么操作可以参考webpack 官网,不过现在都是各种cli 单独使用webpack 已经很少了
const path = require('path');
const webpack = require('webpack');
const presetEnv=require("@babel/preset-env")
module.exports = {
mode: "production",
target: ['web', 'es5', "browserslist"], // 要加这个,这是webpack5.0 的新特性。
entry: {
vendor: [ // 这里是dll 公共打包的。看自己需求,可以放更多。
'vue',
'vue-router',
'vuex',
'vue-i18n',
'axios',
'vuex-persistedstate'
]
},
output: {
path: path.join(__dirname, '../static/js/dll'),
filename: '[name].dll.js',
library: '[name]_library', // vendor.dll.js中暴露出的全局变量名
clean:true,
environment: {
arrowFunction: false
}
},
plugins: [
new webpack.DllPlugin({
path: path.join(__dirname, '.', '[name]-manifest.json'),
name: '[name]_library',
context: path.resolve(__dirname, '..')
})
],
module:{
rules:[{
test:/\.js$/,
use:{
loader:'babel-loader',
options:{
presets:[presetEnv],
}
}
}]
}
};
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map', // IE 会自动解析Map 对于兼容调试很有帮助。
devServer: {
},
module: {
rules: [
{
test: /.css$/,
use: ["style-loader","css-loader"],
},
{
test: /.less$/,
use: ["style-loader",'css-loader', 'less-loader'],
},
],
},
});
const path = require("path");
const { DefinePlugin, DllReferencePlugin } = require('webpack') //dll 打包必须如果不是可以去掉
const HtmlWebpackPlugin = require("html-webpack-plugin"); // 模版主体 没有太大的变化。
const VueLoaderPlugin = require('vue-loader/lib/plugin'); // webpack5.0 vue-loader 的配置方式改变了 主意pagejson版本
const utils = require('./utils')
const WebpackBar = require('webpackbar'); // 打包进度条。默认的很不错,更多 可以参考npm库。
module.exports = {
target: ['web', 'es5', "browserslist"],
entry: {
app: ['core-js',"./src/main.js"], // 兼容IE 必须, 如果IE 不需要可以将core-js 删除
},
output: {
filename: "[name].[contenthash].js",
path: path.resolve(__dirname, "../dist"),
chunkFilename: "[name].[contenthash].js",
clean: true,
publicPath: utils.commonCofig.assetsPublicPath,
pathinfo: utils.commonCofig.pathinfo,
enabledWasmLoadingTypes: ['fetch'],
environment: {
templateLiteral: false, // 默认是true
optionalChaining: false, // 默认是true
module: true, // 默认是false
forOf: false, // 默认是true
dynamicImport: false, // 默认是false,
// dynamicImportInWorker:false, // 默认是false,
destructuring: false,// 默认是true
const: false,// 默认是true
bigIntLiteral: false,// 默认是false
arrowFunction: false // 默认是true
}
},
resolve: {
extensions: [".*", '.js', '.vue', ".json"],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': path.resolve(__dirname, "../src"),
'@static': path.resolve(__dirname, "../static"),
'@common': path.resolve(__dirname, "../src/common"),
'@components': path.resolve(__dirname, "../src/components"),
'@pages': path.resolve(__dirname, "../src/pages"),
'@assets': path.resolve(__dirname, "../src/assets"),
}
},
plugins: [
new HtmlWebpackPlugin({
title: "Production",
template: './public/index.html',
hash: true,
inject: true
}),
new DefinePlugin({
process: {
env: JSON.stringify({ ...utils.commonCofig.env })
},
'_basepath_': JSON.stringify(utils.commonCofig.assetsPublicPath)
}),
new VueLoaderPlugin(),
new DllReferencePlugin({
context: path.resolve(__dirname, '..'),
manifest: require('./vendor-manifest.json')
}),
new WebpackBar(),
],
optimization: {
moduleIds: "deterministic",
runtimeChunk: "single",
splitChunks: {
chunks: "all",
cacheGroups: {
vendeor: {
test: /[\\/]node_modules[\\/]/,
name: "vendeors",
chunks: "all",
}
}
}
},
module: {
rules: [
{
test: /\.vue$/,
include: path.resolve(__dirname, "../src"),
use: [
"vue-loader",
]
},
{
test: /\.(js|vue)$/,
include: path.resolve(__dirname, "../src"),
// exclude: /(node_modules|static)/,
use: [
{
loader: 'thread-loader',
options: {
workers: 40,
}
}]
},
{
test: /\.(js)$/,
include: path.resolve(__dirname, "../src"),
exclude: /(static|node_modules)/, // iE兼容 一定加上static 第三方插件压缩js引用。
use: {
loader: "babel-loader",
}
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
type: "asset/resource",
generator: {
filename: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
type: "asset/resource",
generator: {
filename: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}, {
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: "pre",
include: [path.resolve(__dirname, "../src")],
options: {
formatter: require('eslint-friendly-formatter')
}
}
]
}
};
webpack.prod.js
const { merge } = require("webpack-merge");
const path = require('path')
const common = require("./webpack.common.js");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const CopyWebpackPlugin = require('copy-webpack-plugin')
const config = require('../config')
const utils = require('./utils')
const WebpackBar = require('webpackbar')
module.exports = merge(common, {
mode: "production",
// devtool: "source-map",
module: {
rules: [
{
test: /.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
{
test: /.less$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader'],
},
],
},
optimization: {
minimizer: [
new CssMinimizerPlugin()
]
},
devtool: config.build.productionSourceMap || 'source-map',
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
plugins: [
new MiniCssExtractPlugin({
filename: utils.assetsPath('css/[name].[chunkhash].css'),
chunkFilename: utils.assetsPath('css/[id].[chunkhash].css')
}),
new CopyWebpackPlugin({ // 静态资源拷贝一定要有。
patterns: [{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
}]
}),
new WebpackBar(),
],
optimization: { // 样式分包,每一个组件的私有样式都会打一个单独的样式包。好坏不做评价
splitChunks: {
cacheGroups: {
fooStyles: {
type: 'css/min-extract',
name: "styles_foo",
chunks: (chunk) => {
return chunk.name === "foo"
},
enforce: true,
},
barStyles: {
type: 'css/min-extract',
name: "styles_bar",
chunks: (chunk) => {
return chunk.name === 'bar';
},
enforce: true,
}
}
}
}
});
util.js 配置 // 核心是为了区分环境,如果想自定义变量参考文档
Environment 选项-webpack5.0 APi
环境变量---webpack5.0指南
内置环境变量--node缓存设置。这个个人感觉比较有用,所有记录一下。
const path = require('path')
const config = require('../config')
// 未使用webpack 注入变量, webpack5.0 有很多新特性的变量,参考官网
// npm_lifecycle_event 是取 npm run [name] 的name 字符。
const isProduction = process.env.npm_lifecycle_event !== 'dev'
exports.assetsPath = function (_path) {
const assetsSubDirectory = isProduction
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.commonCofig = isProduction? config.build : config.dev
config/index.js 问配置
const path=require('path')
module.exports={
build:{
index:path.resolve(__dirname,'../dist/index.html'),
assetsRoot:path.resolve(__dirname,'../dist'),
assetsSubDirectory:'./static',
assetsPublicPath:'/prefixName/', //这个是线上服务器配置的,域名/prefixName/页面路由
productionSourceMap:false,
},
dev:{
port:8080,
autoOpenBrowser:true,
assetsSubDirectory:'static',
assetsPublicPath:'/',
proxytable:{ //本地调试接口代理配置。每个项目都不一样,没有参考价值我就不放了
},
cssSourceMap:true
}
}
.babelrc-----babel-lodaer 的配置, 主要是IE 兼容处理,如果没有这个,IE会是空白页面(报js错误。)
{
"presets": [
[
"@babel/preset-env"
]
],
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"corejs": 3
}
],
"@babel/plugin-transform-property-mutators",
"@babel/plugin-transform-arrow-functions",
"@babel/plugin-transform-parameters"
]
}
package.json 文件如下,
npm install之后,一定要执行npx browserslist 查看一下支持的浏览器列表。如何配置请查看browserslist git
{
"name": "webpack5",
"version": "1.0.0",
"sideEffects": true,
"description": "",
"private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"server": "node ./build/server.js", //模拟线上环境
"dev": "webpack serve --open --config ./build/webpack.dev.js",
"build": "webpack --config ./build/webpack.prod.js",
"watch": "webpack --watch"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/cli": "^7.18.10",
"@babel/core": "^7.22.5",
"@babel/plugin-transform-arrow-functions": "^7.18.6",
"@babel/plugin-transform-parameters": "^7.22.5",
"@babel/plugin-transform-property-mutators": "^7.16.7",
"@babel/plugin-transform-runtime": "^7.0.0",
"@babel/preset-env": "^7.20.2",
"@babel/runtime-corejs3": "^7.22.5",
"@types/js-cookie": "^3.0.2",
"axios": "^1.2.2",
"babel-loader": "^9.1.0",
"copy-webpack-plugin": "^11.0.0",
"core-js": "^2.6.12",
"crypto-js": "^3.3.0",
"css-loader": "^6.7.3",
"css-minimizer-webpack-plugin": "^4.0.0",
"eslint": "^7.32.0",
"eslint-friendly-formatter": "^4.0.1",
"eslint-loader": "^4.0.2",
"eslint-plugin-vue": "^9.8.0",
"eslint-webpack-plugin": "^3.2.0",
"eventsource-polyfill": "^0.9.6",
"express": "^4.18.2",
"html-webpack-plugin": "^5.5.0",
"js-cookie": "^2.2.1",
"less": "^4.1.3",
"less-loader": "^10.2.0",
"md5": "^2.3.0",
"mini-css-extract-plugin": "^2.6.1",
"normalize.css": "^8.0.1",
"style-loader": "^3.3.1",
"thread-loader": "^3.0.4",
"vue": "^2.7.14",
"vue-loader": "^15.10.0",
"vue-loader-plugin": "^1.3.0",
"vue-router": "^2.7.0",
"vue-template-compiler": "^2.7.14",
"vuex": "^2.5.0",
"vuex-persistedstate": "^1.3.0",
"webpack": "^5.88.1",
"webpack-cli": "^4.10.0",
"webpack-dev-middleware": "^5.3.3",
"webpack-dev-server": "^3.11.3",
"webpack-hot-middleware": "^2.25.1",
"webpackbar": "^5.0.2"
},
"browserslist": "> 0.1%,not dead,last 3 version",
"dependencies": {
"vue-loader": "^15.10.0"
}
}
附件build/server.js // 主要是模拟生产环境在本地运行。
const express=require('express')
const webpack=require('webpack')
const webpackDevmiddleWare=('webpack-dev-middleware')
const app=express()
const config=require('./webpack.prod')
const compiler=webpack(config)
app.user(webpackDevmiddleWare(compiler,{
publicPath:config.output.publicPath
}))
app.listen(3000,function(){
console.log("Exaplae app listening on port 3000!\n")
})