摘要:介紹背景最近和部門老大,一起在研究團(tuán)隊(duì)前端新手村的建設(shè),目的在于幫助新人快速了解和融入公司團(tuán)隊(duì),幫助零基礎(chǔ)新人學(xué)習(xí)和入門前端開發(fā)并且達(dá)到公司業(yè)務(wù)開發(fā)水平。
介紹 1. 背景
最近和部門老大,一起在研究團(tuán)隊(duì)【EFT - 前端新手村】的建設(shè),目的在于:幫助新人快速了解和融入公司團(tuán)隊(duì),幫助零基礎(chǔ)新人學(xué)習(xí)和入門前端開發(fā)并且達(dá)到公司業(yè)務(wù)開發(fā)水平。
本文也是屬于【EFT - 前端新手村】的一部分,用來幫助新人快速入門 Webpack4,內(nèi)容偏基礎(chǔ),當(dāng)然也可以作為復(fù)習(xí)材料~~這里分享給各位小伙伴啦!
2. 文章概要我將從最基礎(chǔ)的【項(xiàng)目初始化】開始介紹,到【處理 CSS / JS / 圖片】,到【熱更新,打包優(yōu)化】等等,一一介紹和實(shí)踐。
文章共分為 18 章,關(guān)于最基礎(chǔ)的四個(gè)核心概念,可以到我整理的另一篇文章 《Webpack4 的四個(gè)核心概念》 中學(xué)習(xí)。
3. 教程目錄 一、 項(xiàng)目初始化 1. 初始化 demo新建并進(jìn)入文件夾 leo:
mkdir leo cd leo
然后本地安裝 webpack 和 webpack-cli (在 Webpack 4.0以后需要多帶帶安裝):
npm install webpack webpack-cli --save-dev
初始化項(xiàng)目結(jié)構(gòu):
+ ├─package.json + ├─dist // 存放最終打包的文件 + │ └─index.html + ├─src // 存放入口文件等開發(fā)文件 + │ └─index.js + ├─webpack.config.js // webpack的配置文件
安裝 lodash:
npm install lodash --save-dev
--save 可以簡(jiǎn)寫為-S, --save-dev可以簡(jiǎn)寫為-D.
開發(fā) index.js:
import _ from "lodash"; function createElement(){ let div = document.createElement("div"); div.innerHTML = _.join(["my", "name", "is", "leo"], ""); return div; } document.body.appendChild(createElement());
開發(fā) webpack.config.js:
const path = require("path"); module.exports = { entry: "./src/index.js", mode: "development", output: { filename: "main.js", path: path.resolve(__dirname, "dist") } }2. 打包測(cè)試
開始第一次打包任務(wù):
npx webpack // 輸出: Hash: 030b37b6b9a0b4344437 Version: webpack 4.39.1Time: 308ms Built at: 2019-08-07 08:10:21 Asset Size Chunks Chunk Names main.js 552 KiB main [emitted] main Entrypoint main = main.js [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {main} [built] [./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {main} [built][./src/index.js] 225 bytes {main} [built] + 1 hidden module
打包成功后,生成的文件會(huì)保存在 dist 目錄中。
現(xiàn)在在 dist/index.html 中引入打包后的 main.js,打開瀏覽器測(cè)試:
二、 webpack 處理 CSS 模塊這一部分,我們開始學(xué)著使用 webpack 去處理 css 相關(guān)的模塊。
1. 修改代碼在項(xiàng)目 src 目錄中,新建 style 文件夾,并新建 index.css 文件:
├─package.json ├─dist // 存放最終打包的文件 │ └─index.html ├─src // 存放入口文件等開發(fā)文件 │ ├─index.js + │ └─style + │ └─index.css ├─webpack.config.js // webpack的配置文件
接著在 index.js 的新建元素方法中,添加 class 為 box,這樣新建的元素就帶有 box 的 class 屬性:
// src/index.js import _ from "lodash"; import "./style/index.css";// 引入樣式文件 function createElement(){ let div = document.createElement("div"); div.innerHTML = _.join(["my", "name", "is", "leo"], ""); + div.className = "box"; return div; } document.body.appendChild(createElement());
然后在 index.css 文件為 box :
// src/style/index.css .box{ color: red; }
注意:
這里使用 import "./style/index.css"; 引入我們的樣式文件,是沒辦法解析使用,這時(shí)我們需要在 webpack 中使用到第三方 loader 插件,這里我們使用:
css-loader : 用于處理 css 文件,使得能在 js 文件中引入使用;
style-loader : 用于將 css 文件注入到 index.html 中的 標(biāo)簽上;
2. 安裝配置插件安裝插件:
npm install --save-dev style-loader css-loader
再到 webpack.config.js 中添加 css 解析的 loader 配置:
// webpack.config.js module: { rules: [ { test: /.css$/, use: ["style-loader", "css-loader"] } ] }
參數(shù)介紹:
test:需要匹配的模塊后綴名;
use:對(duì)應(yīng)處理的 loader 插件名稱(處理順序是從右往左)。
npx webpack // 輸出: Hash: 28b3965aa1b6a0047536 Version: webpack 4.39.1 Time: 482msBuilt at: 2019-08-09 07:45:25 Asset Size Chunks Chunk Names main.js 565 KiB main [emitted] main Entrypoint main = main.js [./node_modules/_css-loader@3.2.0@css-loader/dist/cjs.js!./src/style/index.css] 190 bytes {main} [built] [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {main} [built][./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {main} [built][./src/index.js] 303 bytes {main} [built] [./src/style/index.css] 447 bytes {main} [built] + 3 hidden modules
這時(shí)候可以看見 index.html 中,文本已經(jīng)變成紅色,并且 css 代碼已經(jīng)添加到 標(biāo)簽上。
三、 webpack 模塊介紹和處理 sass在這一節(jié)中,我們會(huì)介紹 webpack 中的模塊,并且介紹如何去處理 sass 文件。
1. webpack 模塊介紹這里介紹的模塊(module)是指 webpack.config.js 文件中的 module 配置,它決定了如何處理項(xiàng)目中的不同類型模塊。
比如上一節(jié)介紹的,使用 style-loader 、 css-loader 兩個(gè)插件去處理 css 文件。
webpack 模塊支持如下語句:
ES2015 import 語句;
CommonJS require() 語句;
AMD define 和 require 語句;
css/sass/less 文件中 @import 語句;
樣式 (url(...)) 或者 HTML 文件 () 中的圖片鏈接 (image url);
這里建議使用 ES2015 的引入方法,畢竟這是標(biāo)準(zhǔn)。
更多參數(shù)介紹,可訪問中文官網(wǎng)的介紹:2. 常用模塊 2.1 module.noParse
《webpack 配置選項(xiàng)》
值的類型:RegExp | [RegExp] | function
防止 webpack 解析那些符合匹配條件的文件,忽略的文件夾中不應(yīng)該含有 import、require、define的調(diào)用,或任何其他導(dǎo)入機(jī)制,忽略的 library 可以提高構(gòu)建效率。
// webpack.config.js module: { noParse: function(content){ return /jquery|lodash/.test(content); } }2.2 module.rules
創(chuàng)建模塊時(shí),匹配請(qǐng)求的規(guī)則數(shù)組。按照規(guī)則為對(duì)應(yīng)模塊使用對(duì)應(yīng)的 loader,或修改解析器(parser)。
// webpack.config.js module: { rules: [ { test: /.css$/, use: ["style-loader", "css-loader"]} ] }
module.rules 參數(shù)有:
use:為模塊使用指定 loader,并且可以傳入一個(gè)字符串?dāng)?shù)組,加載順序從右往左。
module.rules 匹配條件有:
{test : Condition}:匹配特定條件,非必傳,支持一個(gè)正則表達(dá)式或正則表達(dá)式數(shù)組;
{include : Condition}:匹配特定條件,非必傳,支持一個(gè)字符串或字符串?dāng)?shù)組;
{exclude : Condition}:排除特定條件,非必傳,支持一個(gè)字符串或字符串?dāng)?shù)組;
{and : [Condition]}:必須匹配數(shù)組中的所有條件;
{or : [Condition]}:匹配數(shù)組中任一條件;
{not : [Condition]}:必須排除這個(gè)條件;
更多參數(shù)介紹,可訪問中文官網(wǎng)的介紹:
《Rule》
// webpack.config.js module: { rules: [ { test: /.css$/, use: ["style-loader", "css-loader"], include: [ path.resolve(__dirname, "app/style.css"), path.resolve(__dirname, "vendor/style.css") ] } ] }3. 加載 Sass 文件
需要使用到 sass-loader 的插件,這里先安裝:
npm install sass-loader node-sass --save-dev
在 src/style 目錄下添加 leo.scss 文件,并添加內(nèi)容:
// leo.scss $bg-color: #ee3; .box{ background-color: $bg-color; }
然后在 src/index.js 中引入 leo.scss 文件:
// src/index.js import "./style/leo.scss";
再 npx webpack 重新打包,并打開 dist/index.html 可以看到背景顏色已經(jīng)添加上去:
4. 添加快捷打包命令像 npx webpack 這個(gè)命令我們需要經(jīng)常使用,對(duì)于這種命令,我們可以把它寫成命令,方便每次使用。
我們?cè)?package.json 的 scripts 中添加一個(gè)命令為 build,以后打包只要執(zhí)行 npm run build 即可:
"scripts": { "build": "npx webpack -c webpack.config.js" },
這里的 -c webpack.config.js 中,-c 后面跟著的是 webpack 配置文件的文件名,默認(rèn)可以不寫。
四、 webpack 開啟 SourceMap 和添加 CSS3 前綴添加 SourceMap 是為了方便打包之后,我們?cè)陧?xiàng)目中調(diào)試樣式,定位到樣式在源文件的位置。
1. 開啟 SourceMap在 css-loader 和 sass-loader 都可以通過設(shè)置 options 選項(xiàng)啟用 sourceMap。
// webpack.config.js rules: [ { test: /.(sc|c|sa)ss$/, use: [ "style-loader", { loader:"css-loader", options:{ sourceMap: true } }, { loader:"sass-loader", options:{ sourceMap: true } }, ] } ]
再重新打包,看下 index.html 的樣式,樣式已經(jīng)定位到源文件上了:
這樣我們?cè)陂_發(fā)過程中,調(diào)試樣式就方便很多了。
2. 為樣式添加 CSS3 前綴這里我們用到 PostCSS 這個(gè) loader,它是一個(gè) CSS 預(yù)處理工具,可以為 CSS3 的屬性添加前綴,樣式格式校驗(yàn)(stylelint),提前使用 CSS 新特性,實(shí)現(xiàn) CSS 模塊化,防止 CSS 樣式?jīng)_突。
首先安裝 PostCSS:
npm install postcss-loader autoprefixer --save-dev
另外還有:
postcss-cssnext 可以讓我們使用 CSS4 的樣式,并能配合 autoprefixer 進(jìn)行瀏覽器部分兼容的補(bǔ)全,還支持嵌套語法。
precss 類似 scss 語法,如果我們只需要使用嵌套,就可以用它替換 scss。
postcss-import 讓我們可以在@import CSS文件的時(shí) webpack 能監(jiān)聽并編譯。
更多參數(shù)介紹,可訪問中文官網(wǎng)的介紹:
《postcss-loader》
開始添加 postcss-loader 并設(shè)置 autoprefixer:
// webpack.config.js rules: [ { test: /.(sc|c|sa)ss$/, use: [ "style-loader", { loader:"css-loader", options:{ sourceMap: true } }, { loader:"postcss-loader", options: { ident: "postcss", sourceMap: true, plugins: loader => [ require("autoprefixer")(), // 這里可以使用更多配置,如上面提到的 postcss-cssnext 等 // require("postcss-cssnext")() ] } }, { loader:"sass-loader", options:{ sourceMap: true } }, ] } ]
還需要在 package.json 中添加判斷瀏覽器版本:
// package.json { //... "browserslist": [ "> 1%", // 全球?yàn)g覽器使用率大于1%,最新兩個(gè)版本并且是IE8以上的瀏覽器,加前綴 "last 2 versions", "not ie <= 8" ] }
為了做測(cè)試,我們修改 src/style/leo.scss 中 .box 的樣式:
// src/style/leo.scss .box{ background-color: $bg-color; display: flex; }
然后重新打包,可以看見 CSS3 屬性的前綴已經(jīng)添加上去了:
五、 webpack 將 CSS 抽取成多帶帶文件在之前學(xué)習(xí)中,CSS 樣式代碼都是寫到 index.html 的 標(biāo)簽中,這樣樣式代碼多了以后,很不方便。
于是我們需要將這些樣式打包成多帶帶的 CSS 文件。
webpack4 開始使用 mini-css-extract-plugin 插件,而在 1-3 版本使用 extract-text-webpack-plugin。
注意:抽取樣式以后,就不能使用 style-loader 注入到 html 中。
安裝插件:
npm install mini-css-extract-plugin --save-dev
引入插件:
// webpack.config.js const MiniCssExtractPlugin = require("mini-css-extract-plugin");
然后修改 rules,將 style-loader,替換成 MiniCssExtractPlugin.loader ,然后添加 plugins 配置項(xiàng):
// webpack.config.js module: { rules: [ { test: /.(sc|c|sa)ss$/, use: [ MiniCssExtractPlugin.loader, { loader:"css-loader", options:{ sourceMap: true } }, { loader:"postcss-loader", options: { ident: "postcss", sourceMap: true, plugins: loader => [require("autoprefixer")()] } }, { loader:"sass-loader", options:{ sourceMap: true } }, ] } ] }, plugins: [ new MiniCssExtractPlugin({ filename: "[name].css", // 最終輸出的文件名 chunkFilename: "[id].css" }) ]
然后重新打包,這時(shí)候可以看到我們 dist 目錄下就多了個(gè) main.css 文件:
因?yàn)楝F(xiàn)在已經(jīng)將 CSS 都抽取成多帶帶文件,所以在 dist/index.html 中,我們需要手動(dòng)引入 main.css 了:
// index.html六、 webpack 壓縮 CSS 和 JS
為了縮小打包后包的體積,我們經(jīng)常做優(yōu)化的時(shí)候,將 CSS 和 JS 文件進(jìn)行壓縮,這里需要使用到不同的插件。
1. 壓縮 CSS使用 optimize-css-assets-webpack-plugin 壓縮 CSS 的插件。
安裝插件:
npm install optimize-css-assets-webpack-plugin --save-dev
使用插件:
// webpack.config.js // ... 省略 const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"); module.exports = { // ... 省略 plugins: [ // ... 省略 new OptimizeCssAssetsPlugin({}) ], }
重新打包,可以看到 main.css 已經(jīng)被壓縮成一行代碼,即壓縮成功~
2. 壓縮 JS使用 uglifyjs-webpack-plugin 壓縮 JS 的插件。
安裝插件:
npm install uglifyjs-webpack-plugin --save-dev
引入插件:
// webpack.config.js const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
使用插件:
// webpack.config.js // ... 省略 module.exports = { // ... 省略 plugins: [ // ... 省略 new OptimizeCssAssetsPlugin({}), new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: true }) ], }
其中 UglifyJsPlugin 的參數(shù):
cache:當(dāng) JS 沒有發(fā)生變化則不壓縮;
parallel:是否啟用并行壓縮;
sourceMap:是否啟用 sourceMap;
然后重新打包,查看 main.js,已經(jīng)被壓縮了:
七、webpack 為文件名添加 hash 值由于我們打包出來的 css、js 文件是靜態(tài)文件,就存在緩存問題,因此我們可以給文件名添加 hash 值,防止緩存。
1. 添加 hash 值直接在 webpack.config.js 中,為需要添加 hash 值的文件名添加 [hash] 就可以:
// webpack.config.js module.exports = { // ... 省略其他 output: { filename: "main.[hash].js", path: path.resolve(__dirname, "dist") }, plugins: [ new MiniCssExtractPlugin({ filename: "[name].[hash].css", chunkFilename: "[id].[hash].css" }), ], }
配置完成后,重新打包,就可以看到文件名中包含了 hash 值了:
2. 動(dòng)態(tài)引用打包后的文件由于我們前面給打包的文件名添加了 hash 值,會(huì)導(dǎo)致 index.html 引用文件錯(cuò)誤,所以我們需要讓它能動(dòng)態(tài)引入打包后的文件。
這里我們使用 HtmlWebpackPlugin 插件,它可以把打包后的 CSS 或者 JS 文件直接引用注入到 HTML 模版中,就不用每次手動(dòng)修改。
安裝插件:
npm install html-webpack-plugin --save-dev
引入插件:
// webpack.config.js const HtmlWebpackPlugin = require("html-webpack-plugin");
使用插件:
// webpack.config.js plugins: [ new HtmlWebpackPlugin({ title: "leo study!", // 生成的文件標(biāo)題 filename: "main.html", // 最終生成的文件名 minify: { // 壓縮選項(xiàng) collapseWhitespace: true, // 移除空格 removeComments: true, // 移除注釋 removeAttributeQuotes: true, // 移除雙引號(hào) } }) ],
關(guān)于 html-webpack-plugin 更多介紹可以《查看文檔》https://github.com/jantimon/h...。
接著我們打包以后,可以看見 dist 目錄下,多了 main.html 的文件,格式化以后,可以看出,已經(jīng)動(dòng)態(tài)引入打包后的 CSS 文件和 JS 文件了:
八、 webpack 清理目錄插件在之前,我們每次打包都會(huì)生成新的文件,并且在添加 hash 值以后,文件名不會(huì)出現(xiàn)重復(fù)的情況,導(dǎo)致舊文件的冗余。
為了解決這個(gè)問題,我們需要在每次打包之前,將 /dist 目錄清空,再進(jìn)行打包。
這里我們使用 clean-webpack-plugin 插件來實(shí)現(xiàn)。
安裝插件:
npm install clean-webpack-plugin --save-dev
引入插件:
// webpack.config.js const CleanWebpackPlugin = require("clean-webpack-plugin");
使用插件:
// webpack.config.js plugins: [ new CleanWebpackPlugin() ],
參數(shù) cleanOnceBeforeBuildPatterns 是表示需要清除的文件夾。
這樣我們每次打包之前,都會(huì)先將 /dist 目錄清空一次,再執(zhí)行打包。
更多參數(shù)介紹,可訪問中文官網(wǎng)的介紹:九、 webpack 圖片處理和優(yōu)化 1. 圖片處理
《clean-webpack-plugin》
在項(xiàng)目中引入圖片:
// src/style/leo.scss .box{ background-color: $bg-color; display: flex; background: url("./../assets/logo.jpg") }
這時(shí)候我們?nèi)绻苯哟虬瑫?huì)報(bào)錯(cuò)。
我們需要使用 file-loader 插件來處理文件導(dǎo)入的問題。
安裝插件:
npm install file-loader --save-dev
使用插件:
// webpack.config.js module: { { test: /.(png|svg|jpg|jpeg|gif)$/, use: ["file-loader"] }] },
重新打包以后,發(fā)現(xiàn) dist 目錄下多了一個(gè)如 373e5e0e214390f8aa9e7abb4c7c635c.jpg 名稱的文件,這就是我們打包后的圖片。
2. 圖片優(yōu)化更進(jìn)一步,我們可以對(duì)圖片進(jìn)行壓縮和優(yōu)化,這里我們用到 image-webpack-loader 插件來處理。
安裝插件:
npm install image-webpack-loader --save-dev
使用插件:
// webpack.config.js module: { { test: /.(png|svg|jpg|jpeg|gif)$/, include: [path.resolve(__dirname, "src/")], use: ["file-loader",{ loader: "image-webpack-loader", options: { mozjpeg: { progressive: true, quality: 65 }, optipng: { enabled: false }, pngquant: { quality: "65-90", speed: 4 }, gifsicle: { interlaced: false }, webp: { quality: 75 } } }, ] }] },
更多參數(shù)介紹,可訪問中文官網(wǎng)的介紹:
《image-webpack-loader》
再重新打包,我們可以看到圖片打包前后,壓縮了很大:
十、 webpack 圖片 base64 和字體處理 1. 圖片 base64 處理url-loader 功能類似于 file-loader,可以將 url 地址對(duì)應(yīng)的文件,打包成 base64 的 DataURL,提高訪問效率。
安裝插件:
npm install url-loader --save-dev
使用插件:
注意:這里需要將前面配置的 image-webpack-loader 先刪除掉,在使用 url-loader。
// webpack.config.js module: { { test: /.(png|svg|jpg|jpeg|gif)$/, include: [path.resolve(__dirname, "src/")], use: [ { loader: "url-loader", // 根據(jù)圖片大小,把圖片轉(zhuǎn)換成 base64 options: { limit: 10000 }, }, { loader: "image-webpack-loader", options: { mozjpeg: { progressive: true, quality: 65 }, optipng: { enabled: false }, pngquant: { quality: "65-90", speed: 4 }, gifsicle: { interlaced: false }, webp: { quality: 75 } } }, ] }] },
更多參數(shù)介紹,可訪問中文官網(wǎng)的介紹:2. 字體處理
《url-loader》
字體處理的方式和圖片處理方式是一樣的,只是我們?cè)谂渲?rules 時(shí)的 test 值不相同:
// webpack.config.js module: { { test: /.(woff|woff2|eot|ttf|otf)$/, include: [path.resolve(__dirname, "src/")], use: [ "file-loader" ] } },十一、 webpack 配置合并和提取公共配置
在開發(fā)環(huán)境(development)和生產(chǎn)環(huán)境(production)配置文件有很多不同,但也有部分相同,為了不每次更換環(huán)境的時(shí)候都修改配置,我們就需要將配置文件做合并,和提取公共配置。
我們使用 webpack-merge 工具,將兩份配置文件合并。
安裝插件:
npm install webpack-merge --save-dev
然后調(diào)整目錄結(jié)構(gòu),為了方便,我們將原來 webpack.config.js 文件修改名稱為 webpack.commen.js,并復(fù)制兩份相同的文件出來,分別修改文件名為 webpack.prod.js 和 webpack.dev.js 。
├─package.json ├─dist ├─src - ├─webpack.config.js + ├─webpack.common.js // webpack 公共配置文件 + ├─webpack.prod.js // webpack 生產(chǎn)環(huán)境配置文件 + ├─webpack.dev.js // webpack 開發(fā)環(huán)境配置文件
由于我們文件調(diào)整了,所以在 package.json 中,打包命令也需要調(diào)整,并且配置 mode 模式。
"scripts": { "test": "echo "Error: no test specified" && exit 1", - "build": "npx webpack -c webpack.config.js", + "build": "npx webpack -c webpack.dev.js --mode development", + "dist": "npx webpack -c webpack.prod.js --mode production" },1. 調(diào)整 webpack.common.js
我們先調(diào)整 webpack.common.js 文件,將通用的配置保留,不是通用的配置刪除,結(jié)果如下:
// webpack.common.js const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const { CleanWebpackPlugin } = require("clean-webpack-plugin"); module.exports = { entry: "./src/index.js", module: { noParse: function (content) {return /jquery|lodash/.test(content);}, rules: [ { test: /.(png|svg|jpg|jpeg|gif)$/, include: [path.resolve(__dirname, "src/")], use: [{ loader: "url-loader", // 根據(jù)圖片大小,把圖片轉(zhuǎn)換成 base64 options: { limit: 10000 }, },{ loader: "image-webpack-loader", options: { mozjpeg: { progressive: true, quality: 65 }, optipng: { enabled: false }, pngquant: { quality: "65-90", speed: 4 }, gifsicle: { interlaced: false }, webp: { quality: 75 } } }] },{ test: /.(woff|woff2|eot|ttf|otf)$/, include: [path.resolve(__dirname, "src/")], use: [ "file-loader" ] }] }, plugins: [ new HtmlWebpackPlugin({ title: "leo study!", filename: "main.html", template: path.resolve(__dirname, "src/index.html"), minify: { collapseWhitespace: true, removeComments: true, removeAttributeQuotes: true, } }), new CleanWebpackPlugin() ], }2. 安裝 babel-loader
安裝 babel-loader 是為了將 ES6 及以上版本的 JS 代碼轉(zhuǎn)換成 ES5。
npm install babel-loader @babel/core @babel/preset-env --save-dev
使用插件:
// webpack.common.js rules: [ // ... 省略其他 { test: /.js$/, use: [{ loader: "babel-loader", options: { presets: ["@babel/preset-env"] } }], exclude: /(node_modules|bower_components)/, } ]
關(guān)于 babel-loader 更多介紹可以《查看文檔》https://webpack.js.org/loader...。
3. 調(diào)整 webpack.dev.js這里我們就需要用到 merge-webpack 插件進(jìn)行配置合并了:
// webpack.dev.js const path = require("path"); const merge = require("webpack-merge"); const common = require("./webpack.common.js"); let devConfig = { mode: "development", output: { filename: "main.js", path: path.resolve(__dirname, "dist") }, module: { rules: [{ test: /.(sc|c|sa)ss$/, use: [ "style-loader", { loader: "css-loader", options: { sourceMap: true } }, { loader: "postcss-loader", options: { ident: "postcss", sourceMap: true, plugins: loader => [ require("autoprefixer")() ] } }, { loader: "sass-loader", options: { sourceMap: true } } ] }] } } module.exports = merge(common, devConfig)4. 調(diào)整 webpack.prod.js
同樣對(duì)于生產(chǎn)環(huán)境的配置,我們也需要用 merge-webpack 插件進(jìn)行配置合并:
// webpack.prod.js const path = require("path"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"); const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); const merge = require("webpack-merge"); const common = require("./webpack.common.js"); let prodConfig = { mode: "production", output: { filename: "main.[hash].js", path: path.resolve(__dirname, "dist") }, module: { rules: [{ test: /.(sc|c|sa)ss$/, use: [ MiniCssExtractPlugin.loader, { loader: "css-loader", options: { sourceMap: true } }, { loader: "postcss-loader", options: { ident: "postcss", sourceMap: true, plugins: loader => [ require("autoprefixer")() ] } }, { loader: "sass-loader", options: { sourceMap: true } } ] }] }, plugins: [ new MiniCssExtractPlugin({ filename: "[name].[hash].css", chunkFilename: "[id].[hash].css" }), new OptimizeCssAssetsPlugin({}), new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: true }), ], } module.exports = merge(common, prodConfig)十二、 webpack 監(jiān)控自動(dòng)編譯和啟用 js 的 sourceMap 1. 開啟 js 的 sourceMap
當(dāng) webpack 打包源代碼后,就很難追蹤到錯(cuò)誤和警告在源代碼的位置。
如將三個(gè)源文件打包一個(gè) bundle 中,其中一個(gè)文件的代碼報(bào)錯(cuò),那么堆棧追中就會(huì)指向 bundle。
為了能方便定位錯(cuò)誤,我們使用 inline-source-map 選項(xiàng),注意不要在生產(chǎn)環(huán)境中使用。
// webpack.dev.js let devConfig = { // ... 省略其他 + devtool: "inline-source-map" }2. 測(cè)試 sourceMap
為了測(cè)試是否成功,我們將 src/index.js 代碼中,在第 12 行上,添加一句日志打印。
// src/index.js // ... 省略其他 + console.log(111)
對(duì)比下開啟 sourceMap 前后的區(qū)別:
3. 開啟監(jiān)控自動(dòng)編譯如果每次我們修改完代碼,都要手動(dòng)編譯,那是多累的一件事。
為此我們使用 --watch 命令,讓我們每次保存完,都會(huì)自動(dòng)編譯。
為此,我們需要在 package.json 中的打包命令添加 --watch 命令:
// package.json - "build": "npx webpack --config webpack.dev.js", + "build": "npx webpack --config webpack.dev.js --watch",
這里僅對(duì)開發(fā)環(huán)境開啟,生產(chǎn)環(huán)境不需要使用。
十三、 webpack 熱更新上一節(jié)介紹監(jiān)控自動(dòng)編譯,當(dāng)我們保存文件后,會(huì)自動(dòng)編譯文件,但是我們還是需要手動(dòng)去刷新頁面,才能看到編譯后的結(jié)果。
于是為了自動(dòng)編譯之后,再自動(dòng)重新加載,我們就可以使用 webpack-dev-server 來啟動(dòng)一個(gè)簡(jiǎn)單 web 服務(wù)器,實(shí)時(shí)重新加載。
1. 開啟熱更新插件安裝:
npm install webpack-dev-server --save-dev
使用插件:
// webpack.dev.js const webpack = require("webpack"); const webpack = require("webpack"); let devConfig = { // ... 省略其他 devServer: { contentBase: path.join(__dirname, "dist"), compress: true, hot: true, overlay: true, open:true, publicPath: "/", host: "localhost", port: "1200" } plugins: [ new webpack.NamedModulesPlugin(), // 更容易查看(patch)的以來 new webpack.HotModuleReplacementPlugin() // 替換插件 ] }
啟動(dòng)熱更新:
npx webpack-dev-server --config webpack.dev.js
常用配置:
contentBase: path.join(__dirname, "dist"), //本地服務(wù)器所加載的頁面所在的目錄 clinetLogLevel: "warning", // 可能值有 none, error, warning 或者 info (默認(rèn)值) hot:true,//啟動(dòng)熱更新替換特性,需要配合 webpack.HotModuleReplacementPlugin 插件 host:"0.0.0.0", // 啟動(dòng)服務(wù)器的 host port:7000, // 端口號(hào) compress:true, // 為所有服務(wù)啟用gzip壓縮 overlay: true, // 在瀏覽器中顯示全屏覆蓋 stats: "errors-only" ,// 只顯示包中的錯(cuò)誤 open:true, // 啟用“打開”后,dev服務(wù)器將打開瀏覽器。 proxy: { // 設(shè)置代理 "/api": { target: "http://localhost:3000", pathRewrite: {"^/api" : ""} } }
這時(shí)候我們?cè)L問 http://localhost:1200/main.html 就可以看到頁面,并且修改文件,頁面也會(huì)同時(shí)刷新。
2. 優(yōu)化命令我們可以將 npx webpack-dev-server --config webpack.dev.js 寫到 package.json 中作為一個(gè)命令:
// package.json "scripts": { "test": "echo "Error: no test specified" && exit 1", "build": "npx webpack --config webpack.dev.js --watch", "dist": "npx webpack --config webpack.prod.js", + "watch": "npx webpack-dev-server --config webpack.dev.js" },十四、 webpack 設(shè)置代理服務(wù)器和 babel 轉(zhuǎn)換及優(yōu)化 1. 設(shè)置代理服務(wù)器
接著上一節(jié),接下來給 webpack 設(shè)置代理服務(wù)器:
// webpack.dev.js let devConfig = { // ... 省略其他 devServer: { // ... 省略其他 proxy: { "/api": { // 以 "/api" 開頭的請(qǐng)求,會(huì)跳轉(zhuǎn)到下面的 target 配置 target: "http://192.168.30.33:8080", pathRewrite: { "^api": "/mock/api" } } } }
最后當(dāng)我們請(qǐng)求 /api/getuser 接口,就會(huì)轉(zhuǎn)發(fā)到 http://192.168.30.33:8080/mock/api。
2. babel 轉(zhuǎn)換及優(yōu)化babel-loader 插件的安裝,已經(jīng)提前介紹,在【十一、 webpack 配置合并和提取公共配置】中。
這里講一下 babel-loader 的優(yōu)化。
babel-loader 可以配置 cacheDirectory 來提高打包效率:
cacheDirectory:默認(rèn)值 false,開啟后構(gòu)建時(shí)會(huì)緩存文件夾,后續(xù)從緩存中讀取,將提高打包效率。
十五、 webpack 開啟 Eslint安裝插件:
npm install eslint eslint-loader --save-dev
另外還需要安裝 eslint 解釋器、校驗(yàn)規(guī)則等:
npm install babel-loader standard --save-dev2. 添加 .eslintrc.js
在項(xiàng)目根目錄創(chuàng)建 .eslintrc.js,指定 eslint 規(guī)則。
這份配置內(nèi)容有點(diǎn)多,可以去 我的 gist 復(fù)制https://gist.github.com/pinga... 。
3. 添加 .eslintignore在項(xiàng)目根目錄創(chuàng)建 .eslintignore,指定 eslint 忽略一些文件不校驗(yàn),比如內(nèi)容可以是:
/dist/ /node_modules/十六、 webpack 解析模塊拓展名和別名
在 webpack 配置中,我們使用 resolve 來配置模塊解析方式。
這是非常重要的,比如 import _ from "lodash" ,其實(shí)是加載解析了 lodash.js 文件。
該配置就是用來設(shè)置加載和解析的方式。
在解析過程中,我們可以進(jìn)行配置:
1. resolve.alias當(dāng)我們引入一些文件時(shí),需要寫很長(zhǎng)的路徑,這樣使得代碼更加復(fù)雜。
為此我們可以使用 resolve.alias,創(chuàng)建 import 或 require 的別名,使模塊引入更加簡(jiǎn)單。
使用配置:
// webpack.common.js module.exports = { entry: "./src/index.js", + resolve: { + alias: { + "@" : path.resolve(__dirname, "src/") + } + } // 省略其他 }
alias 參數(shù)的含義:
使用 @ 來替代 path.resolve(__dirname, "src/") 這個(gè)路徑,接下來我們測(cè)試看看。
我們?cè)?src/ 目錄下新增 leo.js:
// leo.js export let name = "pingan";
再到 src/index.js 中引入:
// index.js import { name } from "@/leo.js";
這樣就能正常引入。
當(dāng)然,我們也可以根據(jù)實(shí)際情況,為不同路徑設(shè)置不同別名:
// webpack.common.js alias: { "@" : path.resolve(__dirname, "src/") + "assets" : path.resolve(__dirname, "src/assets/") }
更多參數(shù)介紹,可訪問中文官網(wǎng)的介紹:2. resolve.extensions
《resolve》
resolve.extensions 用來自動(dòng)解析確定的擴(kuò)展,讓我們?cè)谝肽K的時(shí)候,可以不用設(shè)置拓展名,默認(rèn)值為:
extensions: [".js", ".json"]
使用配置:
// webpack.common.js import { name } from "@/leo";十七、 webpack 配置外部拓展
當(dāng)我們使用 CDN 引入 jquery 時(shí),我們并不想把它也打包到項(xiàng)目中,我們就可以配置 externals 外部拓展的選項(xiàng),來將這些不需要打包的模塊從輸出的 bundle 中排除:
配置 externals:
// webpack.common.js module.exports = { // ... 省略其他 + externals: { + jquery: "jQuery" + }, }
通過上面配置,我們就不會(huì)把不需要打包的模塊打包進(jìn)來。并且下面代碼正常運(yùn)行:
import $ from "jquery"; $(".leo").show();
更多參數(shù)介紹,可訪問中文官網(wǎng)的介紹:十八、 webpack 打包分析報(bào)表及優(yōu)化總結(jié) 1. 生成報(bào)表
《externals》
這里我們使用 webpack-bundle-analyzer 插件,來對(duì)打包后的文件進(jìn)行數(shù)據(jù)分析,從來找到項(xiàng)目?jī)?yōu)化的方向。
webpack-bundle-analyzer 使用交互式可縮放樹形圖可視化 webpack 輸出文件的大小。
安裝插件:
npm install webpack-bundle-analyzer --save-dev
這個(gè)我們只有在開發(fā)環(huán)境中使用。
使用插件:
// webpack.dev.js const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin; module.exports = { plugins: [ new BundleAnalyzerPlugin() // ... ] }
配置完成以后,我們執(zhí)行 npm run build 打包,打包完成后,會(huì)自動(dòng)打開一個(gè)數(shù)據(jù)報(bào)表分析的頁面,地址是 http://127.0.0.1:8888/:
webpack-bundle-analyzer 將幫助我們:
看清楚我們包內(nèi)都包含什么模塊;
準(zhǔn)確看出每個(gè)模塊的組成;
最后優(yōu)化它!
我們經(jīng)常將報(bào)表中區(qū)域最大的模塊進(jìn)行優(yōu)化!
2. 通過報(bào)表優(yōu)化項(xiàng)目我們可以看出,打包后的項(xiàng)目中 lodash.js 占了非常大的內(nèi)存,我們就針對(duì) lodash.js 進(jìn)行優(yōu)化。
我們將 lodash.js 改為 CDN 引入:
// index.html
然后去設(shè)置上一節(jié)講到的 externals:
// webpack.common.js externals: { jquery: "jQuery", + lodash: "_" },
再打包以后,可以看到 lodash.js 已經(jīng)不在包里面了:
并且打包后的文件,也能正常運(yùn)行:
更多參數(shù)介紹,可訪問中文官網(wǎng)的介紹:參考資料
《webpack-bundle-analyzer》
《Webpack4 中文網(wǎng)》
《2019最新Webpack4.0教程4.x 成仙之路》
總結(jié)本文是根據(jù) 《2019最新Webpack4.0教程4.x 成仙之路》 學(xué)習(xí)總結(jié)下來的學(xué)習(xí)之路,適合入門,涉及范圍較多,內(nèi)容比較長(zhǎng),需要能靜下心來學(xué)習(xí)。
內(nèi)容如果有誤,歡迎留言指點(diǎn),我會(huì)及時(shí)修改。
本文代碼最終托管在我的 github 上,點(diǎn)擊查看(https://github.com/pingan8787...。
希望自己的文章會(huì)對(duì)各位有所幫助,也歡迎各位大佬指點(diǎn)。
Author | 王平安 |
---|---|
pingan8787@qq.com | |
博 客 | www.pingan8787.com |
微 信 | pingan8787 |
每日文章推薦 | https://github.com/pingan8787... |
ES小冊(cè) | js.pingan8787.com |
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/106732.html
新編html網(wǎng)頁設(shè)計(jì)從入門到精通共分為21章,全面系統(tǒng)地講解了html的發(fā)展歷史及4.0版的新特性、基本概念、設(shè)計(jì)原則、文件結(jié)構(gòu)、文件屬性標(biāo)記、用格式標(biāo)記進(jìn)行頁面排版、使用圖像裝飾頁面、超鏈接的使用、使用表格組織頁面、使用多媒體美化頁面、創(chuàng)建多框架頁面、動(dòng)態(tài)網(wǎng)頁的制作、使用層疊樣式表(css)美化頁面、javascript語言、數(shù)組和字符串以及表達(dá)式與程序的流程控制等內(nèi)容。 本書適合作為培訓(xùn)學(xué)校的...
摘要:微信小程序課程,面向所有具備前端基礎(chǔ)知識(shí)的同學(xué)閱讀要求讀者需要具備但不限于以下技能更佳一共四部分十五小節(jié),適合七天的訓(xùn)練營(yíng)。 ?? 微信小程序課程,面向所有具備前端基礎(chǔ)知識(shí)的同學(xué) ?? 閱讀要求 讀者需要具備但不限于以下技能 HTML JavaScript es6更佳 CSS 一共四部分十五小節(jié),適合七天的訓(xùn)練營(yíng)。 從現(xiàn)在開始,我假裝你已經(jīng)掌握了 html、 css以及 ES6...
摘要:微信小程序課程,面向所有具備前端基礎(chǔ)知識(shí)的同學(xué)閱讀要求讀者需要具備但不限于以下技能更佳一共四部分十五小節(jié),適合七天的訓(xùn)練營(yíng)。 ?? 微信小程序課程,面向所有具備前端基礎(chǔ)知識(shí)的同學(xué) ?? 閱讀要求 讀者需要具備但不限于以下技能 HTML JavaScript es6更佳 CSS 一共四部分十五小節(jié),適合七天的訓(xùn)練營(yíng)。 從現(xiàn)在開始,我假裝你已經(jīng)掌握了 html、 css以及 ES6...
閱讀 3280·2023-04-26 02:42
閱讀 791·2021-10-09 09:41
閱讀 3189·2021-09-06 15:02
閱讀 700·2019-08-26 10:45
閱讀 480·2019-08-23 15:53
閱讀 733·2019-08-22 18:10
閱讀 550·2019-08-22 18:01
閱讀 3516·2019-08-22 17:34