Webpack5正式发布也有很长长长一段时间了,上手了一段时候后发现真香。webpack5的新特性使得咱们在配置上比以往版本更加方便了,构建速度也有了质的飞跃。本文着重为你们讲解从 0 到 1 搭建 vue3 + webpack 5开发环境的过程当中遇到的疑问。css
项目地址: webpack5-vue3html
demo地址: zhouyupeng.github.io/webpack5-vu…前端
先看一下配置好的项目目录结构vue
├─build
│ ├─webpack.base.conf.js
│ ├─webpack.dev.conf.js
│ ├─webpack.prod.conf.js
│ ├─webpack.rules.conf.js
├─node_modules
├─public
| |-index.html
└─src
| ├─api
| ├─assets
| ├─components
| ├─filters
| ├─plugins
| ├─router
| ├─store
| ├─style
| ├─utils
| ├─views
| |-App.vue
| |-main.ts
|-.env.dev
|-.env.test
|-.env.prod
|-.gitigore
|-babel.config.js
|-package.json
|-postcss.config.js
复制代码
接下来,咱们使用 Webpack5
从0搭建一个完整的 Vue3
的开发环境!html5
环境(environment)node
webpack 5 运行于 Node.js v10.13.0+ 的版本。webpack
本文涉及到依赖的版本号ios
├── webpack 5.43
├── webpack-cli 4.7.2
├── node 14.17.0
复制代码
第一步: 建立目录而且初始化 package.json
git
mkdir webpack5-vue3 && cd webpack5-vue3
yarn init -y
复制代码
第二步: 安装webpack三件套github
yarn add webpack webpack-cli webpack-dev-server -D
复制代码
注意:
第三步:初始化目录和文件
./build/webpack.config.js
文件和./src/main.js
文件而且写上webpack打包配置代码// webpack.config.js
const path = require('path');
module.exports = {
entry: path.resolve(__dirname, '../src/main.js'), // 入口
output: {
path: path.resolve(__dirname, '../dist'),
filename: './js/[name].[chunkhash].js',
publicPath: './',
},
}
复制代码
"build": "webpack --config ./build/webpack.config.js --mode production --progress --color -w"
复制代码
运行打包脚本yarn build
看到webpack运行而且打包成功了。
webpack5 + webpack-cli4 启动开发服务器命令与以前有所变化,从 webpack-dev-server 转变为 webpack serve,
"build": "webpack serve --config ./build/webpack.config.js --mode development --progress --color",
复制代码
运行起来后出现了另外的问题。改了代码控制台从新编译,可是热更新无效。
看一下无效的启动和有效启动以后的 network 截图对比:
网上找了一圈,说删除 package.json 里的 browserslist能够热更,截止我写这篇文章安装的依赖版本时不行, 最后在issues看到解决办法,按照官方给出的解释好像只会在webpack-dev-server@4.X中修复这个问题,这里安装beta最新版本yarn add webpack-dev-server@lastest -D
,运行代码发现热更新成功。 安装webpack-dev-server 4.X版本后配置发生了不少改变,废弃了不少之前的配置 4.x配置点我点我或者看这里
在咱们平时项目开发中,通常都会有:开发环境、测试环境、预发布环境和生产环境。如今来对 webpack 的配置文件进行环境拆分。
├─build
│ ├─webpack.base.conf.js //公共配置
│ ├─webpack.dev.conf.js //mode为development配置
│ ├─webpack.prod.conf.js //mode为production配置
│ ├─webpack.rules.conf.js //loader配置
复制代码
使用dotenv
来按需加载不一样的环境变量,VUE CLI3的环境变量也是使用的这个插件
dotenv
插件yarn add dotenv -D
复制代码
webpack.base.conf.js
//...
const envMode = process.env.envMode
require('dotenv').config({ path: `.env.${envMode}` })
// 正则匹配以 VUE_APP_ 开头的 变量
const prefixRE = /^VUE_APP_/
let env = {}
// 只有 NODE_ENV,BASE_URL 和以 VUE_APP_ 开头的变量将经过 webpack.DefinePlugin 静态地嵌入到客户端侧的代码中
for (const key in process.env) {
if (key == 'NODE_ENV' || key == 'BASE_URL' || prefixRE.test(key)) {
env[key] = JSON.stringify(process.env[key])
}
}
plugins: [
//...
new webpack.DefinePlugin({ // 定义环境变量
'process.env': {
...env
}
})
]
复制代码
package.json
"scripts": {
"dev": "cross-env envMode=dev webpack serve --config ./build/webpack.dev.conf.js --color",
"build": "cross-env envMode=prod webpack --config build/webpack.prod.conf.js --color",
"build:test": "cross-env envMode=test webpack --config build/webpack.prod.conf.js --color"
},
复制代码
.env.dev
.env.test
.env.prod
复制代码
配置完成后能够像VUE CLI3同样使用环境变量了点我点我
因为有些浏览器没法解析 ES6+ 等高级语法,故须要将其转化为浏览器可以解析的低版本语法
yarn add @babel/core @babel/preset-env babel-loader -D
yarn add core-js -S
复制代码
loader配置
// webpack.rules.conf.js
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
}
},
]
复制代码
Babel 配置文件 Babel的配置文件是Babel执行时默认会在当前目录寻找的文件,主要有.babelrc,.babelrc.js,babel.config.js和package.json。它们的配置项都是相同,做用也是同样的,只须要选择其中一种。 推荐使用后缀名是js配置文件,由于可使用js作一些逻辑处理,适用性更强。
// babel.config.js
const presets = [
["@babel/preset-env", {
"useBuiltIns": 'usage', // 这里配置usage 会自动根据你使用的方法以及你配置的浏览器支持版本引入对于的方法。
"corejs": "3.11.0" // 指定 corejs 版本
}]
]
const plugins = [
]
module.exports = {
plugins,
presets
}
复制代码
安装 html-webpack-plugin
插件处理 index.html 文件,此插件的功能是根据提供的模板文件,自动生成正确的项目入口文件,并把 webpack 打包的 js 文件自动插入其中
yarn add html-webpack-plugin -D
复制代码
plugins配置
webpack.base.conf.js
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../public/index.html'),
filename: 'index.html',
title: 'webpack5+vue3',
minify: {
html5: true, // 根据HTML5规范解析输入
collapseWhitespace: true, // 折叠空白区域
preserveLineBreaks: false,
minifyCSS: true, // 压缩文内css
minifyJS: true, // 压缩文内js
removeComments: false // 移除注释
},
files: prodMode ? cdn.prod : cdn.dev //CDN引入文件配置
}),
复制代码
这里的index.html源文件放在../public/
文件夹里。 注意: 配置动态网页标题时,需将模板中的 <title>
标签里的内容改为 <%= htmlWebpackPlugin.options.title %>
CDN引入js
<% for (var i in
htmlWebpackPlugin.options.files&&htmlWebpackPlugin.options.files.js) { %>
<script src="<%= htmlWebpackPlugin.options.files.js[i] %>"></script>
<% } %>
复制代码
yarn add style-loader css-loader -D
yarn add node-sass sass-loader -D
yarn add autoprefixer postcss-loader -D
复制代码
loader配置
//webpack.rules.conf.js
{
test: /\.(css|scss|sass)$/,
use: [
'style-loader',
'css-loader',
'postcss-loader',
'sass-loader'
]
}
复制代码
loader 从右到左(或从下到上)地取值(evaluate)/执行(execute)。在上面的示例中,从 sass-loader 开始执行,最后以 style-loader 为结束。
建立 import 或 require 的别名,来确保模块引入变得更简单
// webpack.base.conf.js
resolve: {
alias: {
"@": path.resolve(__dirname, "../src"),
assets: path.resolve(__dirname, '../src/assets/'),
img: path.resolve(__dirname, '../src/assets/img'),
utils: path.resolve(__dirname, '../src/utils'),
api: path.resolve(__dirname, '../src/api'),
},
},
复制代码
Webpack5 以前咱们处理静态资源好比PNG 图片、SVG 图标等等,须要用到url-loader,file-loader,raw-loader。Webpack5 提供了内置的静态资源构建能力,咱们不须要安装额外的 loader,仅须要简单的配置就能实现静态资源的打包和分目录存放。这三个loader在github上也中止了更新。
webpack5使用四种新增的资源模块(Asset Modules)替代了这些loader的功能。
asset/resource 将资源分割为单独的文件,并导出url,就是以前的 file-loader的功能. asset/inline 将资源导出为dataURL(url(data:))的形式,以前的 url-loader的功能. asset/source 将资源导出为源码(source code). 以前的 raw-loader 功能. asset 自动选择导出为单独文件或者 dataURL形式(默认为8KB). 以前有url-loader设置asset size limit 限制实现。
//webpack.rules.conf.js
{
test: /\.(png|jpg|svg|gif)$/,
type: 'asset/resource',
generator: {
// [ext]前面自带"."
filename: 'assets/[hash:8].[name][ext]',
},
}
复制代码
webpack5.20如下版本清除dist文件内容通常使用插件 clean-webpack-plugin, 5.20版本之后output新增特性clean,用于清除dist文件
//webpack.prod.conf.js
module.exports = {
//...
output: {
clean: true, // Clean the output directory before emit.
},
};
复制代码
yarn add copy-webpack-plugin -D
复制代码
当某些文件不须要通过webpack打包处理而直接使用,这里咱们可使用 copy-webpack-plugin
这个插件,在构建的时候,将 public/ 的静态资源直接复制到 dist根目录下
//webpack.prod.conf.js
new copyWebpackPlugin({
patterns: [{
from: path.resolve(__dirname, "../public"),
to: './',
globOptions: {
dot: true,
gitignore: true,
ignore: ["**/index.html*"],
}
}]
}),
复制代码
本插件会将 CSS 提取到单独的文件中,为每一个包含 CSS 的 JS 文件建立一个 CSS 文件,而且支持 CSS 和 SourceMaps 的按需加载。
yarn add mini-css-extract-plugin -D
复制代码
//webpack.prod.conf.js
plugins: [
//...
new miniCssExtractPlugin({
filename: './css/[name].[contenthash].css',
chunkFilename: './css/[id].[contenthash].css',
})
],
复制代码
修改webpack.rules.conf.js
{
test: /\.(css|scss|sass)$/,
use: [
!prodMode ? 'style-loader'
: {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../',
},
},
'css-loader',
'postcss-loader',
'sass-loader',
],
},
复制代码
yarn add vue-loader@next @vue/compiler-sfc -D
yarn add vue@next -S
复制代码
注意:
修改webpack配置
// webpack.rules.conf.js
rules: [
{
test: /\.vue$/,
use: [
'vue-loader'
]
}
]
//webpack.base.conf.js
const { VueLoaderPlugin } = require('vue-loader/dist/index');
plugins: [
new VueLoaderPlugin()
]
复制代码
添加App.vue
<template>
<div>
<p class="title">{{title}}</p>
</div>
</template>
<script>
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const title = ref('渐进式JavaScript 框架');
return {
title
}
}
})
</script>
<style scoped>
.title{
color: #000;
}
</style>
复制代码
修改main.js
import { createApp } from 'vue' // Vue 3.x 引入 vue 的形式
import App from './App.vue' // 引入 APP 页面组建
const app = createApp(App) // 经过 createApp 初始化 app
app.mount('#root') // 将页面挂载到 root 节点
复制代码
跑一遍代码,运行成功。 ####安装Vue全家桶
yarn add vue-router@4 vuex@next axios -S
复制代码
yarn add postcss-loader postcss-px-to-viewport -D
复制代码
新建postcss.config.js文件
'postcss-px-to-viewport': {
unitToConvert: 'px', // 须要转换的单位,默认为"px"
viewportWidth: 750, // 设计稿的视口宽度
unitPrecision: 5, // 单位转换后保留的精度
propList: ['*'], // 能转化为vw的属性列表
viewportUnit: 'vw', // 但愿使用的视口单位
fontViewportUnit: 'vw', // 字体使用的视口单位
selectorBlackList: ['.ignore', '.hairlines', '.ig-'], // 须要忽略的CSS选择器
minPixelValue: 1, // 最小的转换数值,若是为1的话,只有大于1的值会被转换
mediaQuery: false, // 媒体查询里的单位是否须要转换单位
replace: true, // 是否直接更换属性值,而不添加备用属性
include: undefined, // 若是设置了include,那将只有匹配到的文件才会被转换,例如只转换 'src/mobile' 下的文件 (include: /\/src\/mobile\//)
landscape: false, // 是否添加根据 landscapeWidth 生成的媒体查询条件 @media (orientation: landscape)
landscapeUnit: 'vw', // 横屏时使用的单位
landscapeWidth: 568 // 横屏时使用的视口宽度
}
复制代码
使用TerserWebpackPlugin来进行去除console.log
,压缩JS,webpack5以后自带最新的terser-webpack-plugin
,无需再从新安装原文点我点我
//webpack.prod.conf.js
minimizer: [
new TerserPlugin({
// 多进程
parallel: true,
//删除注释
extractComments: false,
terserOptions: {
compress: { // 生产环境去除console
drop_console: true,
drop_debugger: true,
},
},
})
],
复制代码
Webpack5 内置 FileSystem Cache
能力加速二次构建,能够经过如下配置来实现
cache: {
type: 'filesystem',
// 可选配置
buildDependencies: {
config: [__filename], // 当构建依赖的config文件(经过 require 依赖)内容发生变化时,缓存失效
},
name: '', // 配置以name为隔离,建立不一样的缓存文件,如生成PC或mobile不一样的配置缓存
...,
},
复制代码
配置好后第二次构建速度快的飞起。 注意事项:
cache 的属性 type 会在开发模式下被默认设置成 memory
,并且在生产模式中被禁用,因此若是想要在生产打包时使用缓存须要显式的设置。
为了防止缓存过于固定,致使更改构建配置无感知,依然使用旧的缓存,默认状况下,每次修改构建配置文件都会致使从新开始缓存。固然也能够本身主动设置 version
来控制缓存的更新。
yarn add vant@next -S
复制代码
yarn add babel-plugin-import -D
复制代码
// babel.config.js
const plugins = [
['import', {
libraryName: 'vant',
libraryDirectory: 'es',
style: true
}, 'vant']
]
复制代码
修改postcss.config.js
const path = require('path');
module.exports = ({file}) => {
const designWidth = file.includes(path.join('node_modules', 'vant')) ? 375 : 750;// vant团队是根据375px的设计稿去作的
return {
plugins: {
'postcss-px-to-viewport': {
unitToConvert: 'px', // 须要转换的单位,默认为"px"
viewportWidth: designWidth, // 设计稿的视口宽度
unitPrecision: 5, // 单位转换后保留的精度
propList: ['*'], // 能转化为vw的属性列表
viewportUnit: 'vw', // 但愿使用的视口单位
fontViewportUnit: 'vw', // 字体使用的视口单位
selectorBlackList: ['.ignore', '.hairlines', '.ig-'], // 须要忽略的CSS选择器
minPixelValue: 1, // 最小的转换数值,若是为1的话,只有大于1的值会被转换
mediaQuery: false, // 媒体查询里的单位是否须要转换单位
replace: true, // 是否直接更换属性值,而不添加备用属性
include: undefined, // 若是设置了include,那将只有匹配到的文件才会被转换,例如只转换 'src/mobile' 下的文件 (include: /\/src\/mobile\//)
landscape: false, // 是否添加根据 landscapeWidth 生成的媒体查询条件 @media (orientation: landscape)
landscapeUnit: 'vw', // 横屏时使用的单位
landscapeWidth: 568 // 横屏时使用的视口宽度
}
}
}
}
复制代码
yarn add webpack-bundle-analyzer -D
复制代码
用来分析哪些模块引入了哪些代码,进行有目的性的优化代码 在打包脚本后面加--analyze
如yarn build --analyze
,无需另外配置。新版本webpack-cli已经支持了。原文
不知道你们看完这篇文章,学废了吗。文章中如果有错误或者不许确的地方,欢迎你们指出讨论。
欢迎关注小程序“进阶的大前端
”,800多道前端面试题在线查看