细数着2020年,从疫情开始就没好事发生过,作为一个半专业的前端bug工程师看着vue3发布了,webpack5发布了,react17发布了,除了react17这一两月都在可劲的盘,今天来聊一聊盘webpack5的血泪史!
开始之前自个儿准备好node>=10,(c)npm,当然你要用yarn也可以,我这里用不了npm,用的是cnpmv6.1.1
,nodev12.18.4
,不信你就看下面的截图:
一、首先创建文件夹webpack5,并初始化项目 cnpm init -y
,得到package.json
二、安装依赖
- webpack相关
cnpm i -D webpack webpack-cli webpack-dev-server
安装好了webpack是如下这样的
- 其他依赖
cnpm i -D cross-env babel-loader html-webpack-plugin mini-css-extract-plugin clean-webpack-plugin style-loader css-loader vue-style-loader html-loader @babel/core
三、安装vue相关
cnpm i -S vue vue-router
cnpm i -D vue-template-compiler vue-loader
注意 vue和vue-template-compiler版本号一定要一样
四、在webpack5目录下webpack.config.js
- 编辑config
const { resolve, join } = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 自动生成index.html
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // 文本分离插件,分离js和css
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 清理垃圾文件
const { VueLoaderPlugin } = require('vue-loader'); // vue加载器
const port = 3002;
const isProd = process.env.NODE_ENV === 'production';
const cssConfig = [
isProd ? MiniCssExtractPlugin.loader : 'vue-style-loader',
{
loader: 'css-loader',
options: {
sourceMap: !isProd
}
}
];
const config = {
entry: {
index: './src/index.js' // 入口文件
},
output: {
path: resolve(__dirname, 'dist'),
filename: isProd ? 'javascript/[name].[contenthash:5].js' : '[name].js', // [name] 是entry的key
publicPath: isProd ? './' : '/'
},
module: {
rules: [
{
test: /\.css$/i,
use: cssConfig
},
{
test: /\.vue$/,
use: [
{
loader: 'vue-loader',
options: {
loaders: {
css: cssConfig
},
preserveWhitespace: false // 不要留空白
}
}
],
include: [resolve(__dirname, 'src')]
},
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: !isProd
}
}
],
exclude: /node_modules/,
},
{
test: /\.html$/,
use: [{
loader: 'html-loader',
options: { // 配置html中图片编译
minimize: true,
attributes: false
}
}]
}
]
},
resolve: { // 配置路径别名
extensions: ['.js', '.vue', '.styl'] // import引入文件的时候不用加后缀
},
plugins: [
new VueLoaderPlugin(), // vue加载器
new HtmlWebpackPlugin({
template: join(__dirname, 'src/index.html'), // 引入模版
filename: 'index.html',
minify: { // 对index.html压缩
collapseWhitespace: isProd, // 去掉index.html的空格
removeAttributeQuotes: isProd // 去掉引号
},
hash: true, // 去掉上次浏览器的缓存(使浏览器每次获取到的是最新的html)
inlineSource: '.(js|css)'
}),
new MiniCssExtractPlugin({ // 分离css
filename: 'stylesheets/[name].[contenthash:5].css'
})
]
};
if (isProd) {
config.plugins.push(
new CleanWebpackPlugin({
verbose: true, // 打印被删除的文件
protectWebpackAssets: false, // 允许删除cleanOnceBeforeBuildPatterns中的文件
cleanOnceBeforeBuildPatterns: ['**/*', resolve(__dirname, 'dist')]
}),
new MiniCssExtractPlugin({ // 分离css
filename: 'stylesheets/[name].[contenthash:5].css'
})
);
config.optimization = { // 抽离第三方插件
minimize: true,
splitChunks: {
chunks: 'all', // 必须三选一: "initial" | "all" | "async"(默认就是异步)
minChunks: 3, // 共享最少的chunk数,使用次数超过这个值才会被提取
maxAsyncRequests: 5, // 最多的异步chunk数
maxInitialRequests: 5, // 最多的同步chunks数
cacheGroups: { // 这里开始设置缓存的 chunks
vendor: { // key 为entry中定义的 入口名称,new webpack.ProvidePlugin中的库
test: /node_modules/, // 正则规则验证,如果符合就提取 chunk (指定是node_modules下的第三方包)
// test: /[\\/]node_modules[\\/](vue|vue-router|vuex)[\\/]/, // 正则规则验证,如果符合就提取 chunk (指定是node_modules下的第三方包)
name: 'vendor', // 要缓存的 分隔出来的 chunk 名称
enforce: true,
},
main: {
test: /src/,
name: 'main',
enforce: true,
}
}
},
runtimeChunk: { name: 'runtime' } // 为每个入口提取出webpack runtime模块
};
} else {
config.plugins.push(
new webpack.HotModuleReplacementPlugin(),
);
config.devtool = 'eval-source-map'; // 如果只用source-map开发环境出现错误定位源文件,生产环境会生成map文件
config.devServer = {
contentBase: join(__dirname, 'dist'), // 将 dist 目录下的文件,作为可访问文件。
compress: true, // 开启Gzip压缩
host: 'localhost', // 设置服务器的ip地址,默认localhost
port, // 端口号
open: true, // 自动打开浏览器
hot: true,
noInfo: true,
overlay: { // 当出现编译器错误或警告时,就在网页上显示一层黑色的背景层和错误信息
errors: true
},
disableHostCheck: true // 不检查主机
};
}
module.exports = config;
- 编辑package.json
在package.json的scripts处添加
"dev": "cross-env NODE_ENV=development webpack-dev-server --mode development",
"prod": "cross-env NODE_ENV=production webpack --mode production"
五、在webpack5目录下新建src目录,在src下新建index.html、index.js、router.js、App.vue、Demo.vue,编写相关代码
1.index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webpack5</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
- index.js
import Vue from 'vue';
import router from './router';
import App from './App';
const isProd = process.env.NODE_ENV === 'production';
Vue.config.productionTip = isProd;
new Vue({
router,
render: (h) => h(App)
}).$mount('#app');
- router.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import Demo from './Demo';
Vue.use(VueRouter);
export default new VueRouter({
routes: [
{
path: '/demo',
name: 'Demo',
component: Demo,
meta: {
title: 'Demo'
}
}
]
});
- App.vue
<template>
<div>
<div class="app">APP</div>
<router-link to="/demo">to demo page</router-link>
<router-view/>
</div>
</template>
<script>
export default {
name: "App"
}
</script>
<style scoped>
.app {
font-size: 14px;
color: aquamarine;
}
</style>
- Demo.vue
<template>
<div class="demo">Demo</div>
</template>
<script>
export default {
name: "Demo"
}
</script>
<style scoped>
.demo {
font-size: 16px;
color: blueviolet;
}
</style>
六、试运行
启动项目cnpm run dev
报错信息 Error: Cannot find module 'webpack-cli/bin/config-yargs'
大概猜测意思是找不到webpack-cli下的某个模块
在没升级到webpack5之前并没有这样的报错,这个问题使我 这半个月以来都不开心
于是我翻开以前的代码查找官方文档反复研究也没有答案,甚至翻遍全中国网都没有给我答案,欲哭无泪
于是我放弃了使用wbpack5
我想 官方的意思是,反正我是发布了,用不用随你
半个月后,wbpack5已经更新到了5.2.0,我重新入坑,既然webpack-cli@4版本没有config-yargs模块,那我用3.x版本可否?
于是我重新安装 cnpm i -D webpack-cli@3
重新启动——成功!
七、总结
由此可以看出,不是所有的新东西都是好东西,总要踩许多坑,就如我在使用webpack4的时候,升级了css-loader@4版本,编译也会报错
学习总是循序渐进的,是我太急躁不开心了半个月