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多道前端面試題在線查看