上篇文章簡單的介紹了一下,前端進階之腳手架的搭建。其實我我的認爲重要的仍是Webpack的配置出來的template,至於腳手架的交互體驗能夠後期去優化,也能夠更加的個性化。可是咱們的核心仍是放在Webpack等一系列的配置上。javascript
這篇文章的目的css
好了,收!話很少說開始!html
相信來到這裏的小夥伴,都是有一些些前端的經驗了,至於什麼node安裝環境變量這裏就不贅述了。本人使用的是mac os,若是是Windows的而且碰到問題的話,能夠留言,或者直接Google。前端
新建一個文件夾,名爲【webpackInit】java
而且使用你的編輯器打開他,而後打開命令行執行:node
npm init -y
複製代碼
這個命令是node幫你初始化一個項目用的,幫你新建一個package.json
。react
至於-y
是用於默認都以yes繼續執行。若是想了解一下里面到底有什麼的同窗能夠不用*-y*繼續跑一遍。其實裏面的東西后期均可以本身修改package.json
。因此不須要太在乎。android
如今是北京時間:2020/06/07 06:42:49。webpack
Webpack5有Beta版,這裏就不考慮了,後續上正式版的話我應該會出新的文章介紹。ios
由於咱們使用的是 webpack 4+
版本,還須要安裝 webpack-cli
,執行如下命令:
npm install --save-dev webpack webpack-cli
複製代碼
由於Webpack主要是編譯時使用因此放到「devDependencies」。
確認一下如今的目錄結構,以防有同窗掉隊!
webpackInit
|- node_modules
|- package-lock.json
|- package.json
複製代碼
這裏說下題外話。
package.json 文件只能鎖定大版本,也就是版本號的第一位,並不能鎖定後面的小版本,npm install
都是拉取的該大版本下的最新的版本,爲了穩定性考慮咱們幾乎是不敢隨意升級依賴包的,這將致使多出來不少工做量,測試/適配等,因此 package-lock.json 文件出來了,當你每次安裝一個依賴的時候就鎖定在你安裝的這個版本。
那若是咱們安裝時的包有bug,後面須要更新怎麼辦?
在之前可能就是直接改 package.json 裏面的版本,而後再 npm install
了,可是 5 版本後就不支持這樣作了,由於版本已經鎖定在 package-lock.json 裏了,因此咱們只能 npm install xxx@x.x.x
這樣去更新咱們的依賴,而後 package-lock.json 也能隨之更新。
咱們在根目錄新建文件夾【config】用於存儲一些相關的配置文件,而後在【config】裏面新建一個文件夾【webpack】表示,專門用於存儲webpack的配置文件。而後在【webpack】這個文件夾下面新建文件【webpack.common.config.js】
並敲入如下代碼
const path = require('path');
module.exports = {
// 配置入口文件
entry: {
app: './src/index.js',
},
// 打包📦以後的出口
output: {
// 若是不加哈希值,瀏覽器會有緩存,可能你部署了,可是用戶看到的仍是老頁面
// 8是hash的長度,若是不設置,webpack會設置默認值爲20。
filename: 'js/[name].[chunkhash:8].bundle.js',
/** * Node.js 中,__dirname 老是指向被執行 js 文件的絕對路徑, * 因此當你在 /d1/d2/myscript.js 文件中寫了 __dirname, 它的值就是 /d1/d2 。 * path.resolve * 1.path.resolve()方法能夠將路徑或者路徑片斷解析成絕對路徑 * 2.傳入路徑從右至左解析,遇到第一個絕對路徑是完成解析,例如path.resolve('/foo', '/bar', 'baz') 將返回 /bar/baz * 3.若是傳入的絕對路徑不存在,那麼當前目錄將被使用 * 4.當傳入的參數沒有/時,將被傳入解析到當前根目錄 * 5.零長度的路徑將被忽略 * 6.若是沒有傳入參數,將返回當前根目錄 * * _dirname表示絕對路徑 * 咱們碰到的./xx就是相對路徑 * 1.只傳入__dirname也能夠自動調用path.resolve方法 * 2.能夠拼接路徑字符串,可是不調用path.resolve()方法拼接失敗 * 3.__dirname表明的是當前文件(a.js)的絕對路徑 * 4.從右至左解析,遇到了絕對路徑/src,所以直接返 */
path: path.resolve(__dirname, '../../dist')
}
}
複製代碼
webpack 配置是標準的 Node.js的CommonJS 模塊,它經過require來引入其餘模塊,經過module.exports導出模塊,由 webpack 根據對象定義的屬性進行解析。
在根目錄新建【src】文件夾📁
在【src】文件夾下新建文件index.js
ok👌,確認一下目錄結構
webpackInit
+ |- config
+ |- webpack
+ |- webpack.common.config.js
|- node_modules
+ |- src
+ |- index.js
|- package.json
|- package-lock.json
複製代碼
那咱們怎麼打包呢?在 package.json
中配置以下屬性:
"scripts": {
- "test": "echo \"Error: no test specified\" && exit 1",
+ "start": "webpack --config ./config/webpack/webpack.common.config.js"
},
複製代碼
好了,咱們試試怎麼打包吧,雖然你的 index.js
中什麼代碼也沒有。 在控制檯中輸入如下代碼:
npm run start
複製代碼
npm run xxxx 會去執行當前目錄下package.json裏面的script同名腳本
咱們的【npm run start】至關於直接執行了咱們寫在【start】裏面的代碼。
執行以後,你會發現根目錄多出了一個文件夾: dist/js
,其中有一個js文件: bundle.js
,那麼至此,咱們已經成功編譯打包了一個js文件,即入口文件: index.js
。
在控制檯輸入如下代碼:
npm install --save react react-dom
複製代碼
--save就是運行時會用到的代碼
具體和--dev-save的區別能夠本身Google一下
在【src/index.js】裏面加入如下代碼
import React from 'react';
import ReactDOM from 'react-dom';
const App = () => (
<> Hello World! </> ) ReactDOM.render(<App />, document.getElementById('root')); 複製代碼
在根目錄加入文件夾【public】,而後在【public】裏面加入【index.html】
目錄以下:
webpackInit
+ |- public
+ |- index.html
|- config
|- webpack
|- webpack.common.config.js
|- node_modules
|- src
|- index.js
|- package.json
|- package-lock.json
複製代碼
而後在【index.html】加入如下代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<title>從零配置Webpack</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
複製代碼
OK
萬事俱備,咱們運行:
npm run start
複製代碼
打包失敗了。。。爲何呢?
爲何咱們上面寫jsx會打包不了呢,由於webpack根本識別不了jsx語法,那怎麼辦?使用loader對文件進行預處理。 其中,babel-loader,就是這樣一個預處理插件,它加載 ES2015+ 代碼,而後使用 Babel 轉譯爲 ES5。那開始配置它吧!
首先安裝babel相關的模塊:
npm install --save-dev babel-loader @babel/preset-react @babel/preset-env @babel/core babel-plugin-import
複製代碼
理論上咱們能夠直接在 webpack.common.config.js
中配置"options",但最好在當前根目錄,注意,必定要是根目錄!!! 新建一個配置文件 .babelrc
配置相關的"presets":
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
// 大於相關瀏覽器版本無需用到 preset-env
"edge": 17,
"firefox": 60,
"chrome": 67,
"safari": 11,
// 兼容到android4 ios6
"browsers": ["Android >= 4.0", "ios >= 6"]
}
}
],
"@babel/preset-react"
],
"plugins": [
["import", { "libraryName": "antd-mobile", "style": "css" }] // `style: true` 會加載 less 文件
]
}
複製代碼
這裏有關bebel的配置可上官網查詢文檔。
再修改 webpack.common.config.js
,添加以下代碼:
const path = require('path');
module.exports = {
// 配置入口文件
entry: {
app: './src/index.js',
},
// 打包📦以後的出口
output: {
// 若是不加哈希值,瀏覽器會有緩存,可能你部署了,可是用戶看到的仍是老頁面
// 8是hash的長度,若是不設置,webpack會設置默認值爲20。
filename: 'js/[name].[chunkhash:8].bundle.js',
/** * Node.js 中,__dirname 老是指向被執行 js 文件的絕對路徑, * 因此當你在 /d1/d2/myscript.js 文件中寫了 __dirname, 它的值就是 /d1/d2 。 * path.resolve * 1.path.resolve()方法能夠將路徑或者路徑片斷解析成絕對路徑 * 2.傳入路徑從右至左解析,遇到第一個絕對路徑是完成解析,例如path.resolve('/foo', '/bar', 'baz') 將返回 /bar/baz * 3.若是傳入的絕對路徑不存在,那麼當前目錄將被使用 * 4.當傳入的參數沒有/時,將被傳入解析到當前根目錄 * 5.零長度的路徑將被忽略 * 6.若是沒有傳入參數,將返回當前根目錄 * * _dirname表示絕對路徑 * 咱們碰到的./xx就是相對路徑 * 1.只傳入__dirname也能夠自動調用path.resolve方法 * 2.能夠拼接路徑字符串,可是不調用path.resolve()方法拼接失敗 * 3.__dirname表明的是當前文件(a.js)的絕對路徑 * 4.從右至左解析,遇到了絕對路徑/src,所以直接返 */
path: path.resolve(__dirname, '../../dist')
},
module: {
/** * test 規定了做用於以規則中匹配到的後綴結尾的文件, * use 便是使用 babel-loader 必須的屬性, * exclude 告訴咱們不須要去轉譯"node_modules"這裏面的文件。 */
rules:[
{
test: /\.(js|jsx)?$/,
// 開啓緩存
options: { cacheDirectory: true },
loader: 'babel-loader',
},
]
}
}
複製代碼
接下來激動人心的時刻:
npm run start
複製代碼
是否是能打包成功了呢?
打開【dist/】你的html頁面,看一下是不是「Hello World!」吧!
咱們將使用一個名爲 webpack-merge 的工具。經過「通用」配置,咱們沒必要在環境特定(environment-specific)的配置中重複代碼。簡單來講就是生產環境不一樣,咱們要給的配置也有所不一樣,可是能夠共用一個共有的配置。
咱們先從安裝 webpack-merge 開始:
npm install --save-dev webpack-merge
複製代碼
安裝結束以後,咱們在 config
這個文件夾下新建兩個文件,分別爲 webpack.prod.config.js
和 webpack.dev.config.js
,這兩個文件分別對應生產和開發兩個環境的配置。固然你也能夠添加test環境。名字也能夠本身取,儘可能保持一致。
如今的目錄結構:
webpackInit
|- config
|- webpack
|- webpack.common.config.js
+ |- webpack.prod.config.js
省略
複製代碼
在【webpack.prod.config.js】加入
const merge = require('webpack-merge'); // 版本爲4.x
// webpack-merge 5.x版本應該改成 const { merge } = require('webpack-merge');
const common = require('./webpack.common.config.js');
module.exports = merge(common, {
mode: 'production',
});
複製代碼
而後修改【package.json】
{
"name": "webpackInit",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack --config ./config/webpack/webpack.common.config.js",
+ "build": "webpack --config ./config/webpack/webpack.prod.config.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.10.2",
"@babel/preset-env": "^7.10.2",
"@babel/preset-react": "^7.10.1",
"babel-loader": "^8.1.0",
"babel-plugin-import": "^1.13.0",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11",
"webpack-merge": "^4.2.2"
},
"dependencies": {
"react": "^16.13.1",
"react-dom": "^16.13.1"
}
}
複製代碼
而後
刪除【dist文件夾】
以後
npm run build
複製代碼
是否是也build也打包成功了!
html是否是也能夠正常訪問!
可是沒有顯示Hello World,仔細一看還報錯了。。。爲何呢。。由於
// 若是不加哈希值,瀏覽器會有緩存,可能你部署了,可是用戶看到的仍是老頁面
// 8是hash的長度,若是不設置,webpack會設置默認值爲20。
filename: 'js/[name].[chunkhash:8].bundle.js',
複製代碼
咱們給js文件設置了hash值。不可以直接在html裏面加上【】這麼一句,並且每次生成的hash值都會變,那麼咱們要怎麼處理這個問題呢?
在控制檯執行如下代碼:
npm install --save-dev html-webpack-plugin
複製代碼
修改【webpack.prod.config.js】
const merge = require('webpack-merge'); // 版本爲4.x
// webpack-merge 5.x版本應該改成 const { merge } = require('webpack-merge');
const common = require('./webpack.common.config.js');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = merge(common, {
mode: 'production',
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html', // 打包以後的html文件名字
// 這裏有小夥伴可能會疑惑爲何不是 '../public/index.html'
// 個人理解是不管與要用的template是否是在一個目錄,都是從根路徑開始查找
template: 'public/index.html', // 以咱們本身定義的html爲模板生成,否則咱們還要到打包以後的html文件中寫script
inject: 'body',// 在body最底部引入js文件,若是是head,就是在head中引入js
minify: { // 壓縮html文件
removeComments: true, // 去除註釋
collapseWhitespace: true, // 去除空格
},
})
]
});
複製代碼
如今咱們再來打包試試
npm run build
複製代碼
看看dist中是否是多出了html文件,而且自動引入了script,用瀏覽器打開它試試看是否是能正確輸出內容了!
起飛!!🛫️
有些同窗已經厭倦了每次都須要刪除dist文件夾來驗證是否成功。
其實假如咱們不刪除的話,咱們須要修改js文件,這樣讓webpack知道咱們改了東西,他就會從新打包,可是咱們每次測試都沒有去修改,因此咱們須要刪除。
可是,若是說咱們不去刪除dist文件夾的話,咱們修改了【src/index.js】。而後再從新build,就會發現【dist/js】下面會又多出一個js文件,這樣的話咱們就須要觀察日誌,查看新鮮「出爐」的是哪個,而後刪掉別的。這樣很是麻煩。
OK,咱們如今就來解決一下這個問題
安裝clean-webpack-plugin
npm install --save-dev clean-webpack-plugin
複製代碼
修改【webpck.prod.config.js】
const merge = require('webpack-merge'); // 版本爲4.x
// webpack-merge 5.x版本應該改成 const { merge } = require('webpack-merge');
const common = require('./webpack.common.config.js');
const HtmlWebpackPlugin = require('html-webpack-plugin');
+ const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = merge(common, {
mode: 'production',
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html', // 打包以後的html文件名字
// 這裏有小夥伴可能會疑惑爲何不是 '../public/index.html'
// 個人理解是不管與要用的template是否是在一個目錄,都是從根路徑開始查找
template: 'public/index.html', // 以咱們本身定義的html爲模板生成,否則咱們還要到打包以後的html文件中寫script
inject: 'body',// 在body最底部引入js文件,若是是head,就是在head中引入js
minify: { // 壓縮html文件
removeComments: true, // 去除註釋
collapseWhitespace: true, // 去除空格
},
}),
+ new CleanWebpackPlugin()
]
});
複製代碼
咱們先查看如今的js文件前面的hash值。而後咱們修改【src/index.js】,隨便改爲什麼,再從新
npm run build
複製代碼
就會發現文件並無新增,並且換了新鮮的哈希值。
固然了,我以前說的那些話,同窗不相信的話,能夠把【new CleanWebpackPlugin()】這一行註釋掉,而後再修改【src/index.js】,會發現【dist/js】下面的js文件會增多一條。
既然剛剛都提到優化了,咱們每次都須要build一下,感受很呆。而webpack官方也提供熱部署,那咱們如今就使用起來
安裝webpack-dev-server
npm install webpack-dev-server --save-dev
複製代碼
新建文件【webpack.dev.config.js】📃
webpackInit
|- config
|- webpack
|- webpack.common.config.js
|- webpack.prod.config.js
+ |- webpack.dev.config.js
省略
複製代碼
而後加入以下代碼
const path = require('path');
const merge = require('webpack-merge'); // 版本爲4.x
// webpack-merge 5.x版本應該改成 const { merge } = require('webpack-merge');
const common = require('./webpack.common.config.js');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = merge(common, {
mode: 'development',
output: {
filename: 'js/[name].[hash:8].bundle.js',
},
devServer: {
contentBase: path.resolve(__dirname, '../dist'),
open: true,
port: 9000,
compress: true,
hot: true
},
plugins: [
new HtmlWebpackPlugin({
template: 'public/index.html',
inject: 'body',
hash: false
}),
new webpack.HotModuleReplacementPlugin()
]
});
複製代碼
修改文件【package.json】📃
"scripts": {
- "start": "webpack --config ./config/webpack/webpack.common.config.js",
+ "start": "webpack-dev-server --inline --config ./config/webpack/webpack.dev.config.js",
"build": "webpack --config ./config/webpack/webpack.prod.config.js",
},
複製代碼
而後咱們
npm run start
複製代碼
是否是自動開了一個端口爲9000的網頁,上面是咱們寫的頁面內容,這和咱們的配置都是一一對應的。 如今你隨意修改index.js中的代碼,再回到頁面看下是否是也跟着變了,那咱們就整合webpack-dev-server成功!
source-map能夠展現咱們代碼的錯誤位置,由於咱們的代碼都是被webpack打包過的,只有機器看得懂,咱們人類沒法正常識別。因此須要他。
想試一下未開啓是什麼狀態的同窗能夠本身故意把代碼寫錯,而後看看控制檯的報錯。
開啓也十分簡單。
它的配置很是簡單,只須要在 【webpack.dev.config.js】 中增長一個 devtool
屬性便可!
module.exports = {
+ devtool: 'cheap-module-eval-source-map',
//...
}
複製代碼
由於咱們只有本身寫代碼的時候才須要查看,到生產環境就要關閉啦,否則咱們的智慧結晶就要被【竊取】啦!因此我放在了
這裏回顧一下知識點。
基本上上述的操做過程我都有解釋,或者是註釋,或者是在文章中說明。你們能夠跟着節奏一步一步來,由於我也是一邊寫blog一邊跑代碼一邊回顧知識點。
至此,webpack算是告一……
誒誒誒誒!js是能夠解析了,那css呢!
哦哦,好的,那咱們繼續啓程
假如咱們直接引用css的話,會報錯了。這裏就不演示了,有興趣的同窗能夠本身試試。
因此,咱們先走命令行敲擊
npm install --save-dev style-loader css-loader
複製代碼
來講說css-loader和style-loader他們這對鴛鴦的關係。
首先css-loader會把你的CSS文件進行解析,由於webpack是用JS寫的,運行在node環境,因此默認webpack打包的時候只會處理JS之間的依賴關係!
因此咱們以前的react裏面的jsx須要babel的幫助,或者說須要【babel-loader】的幫助,因此咱們的css一樣須要【css-loader】的幫助,那麼又關【style-loader】什麼事?可不能夠不裝他呢?
答案是:能夠的,可是你使用起來會很是的麻煩。怎麼個麻煩法呢?
若是隻用了【css-loader】解析出來的是這樣的
["./src/index.css", ".test{↵ color: red;↵}", ""]
複製代碼
這樣咋用嘛,你是解析了,但是你解析的是個XX。
這個時候就須要咱們的天降猛男【style-loader】
style-loader 是經過一個JS腳本建立一個style標籤,裏面包含一些樣式。style-loader是不能單獨使用的,應爲它並不負責解析 css 以前的依賴關係,每一個loader的功能都是單一的,各自拆分獨立。
加入index.css
src
+ |- index.css
|- indexjs
複製代碼
index.css文件的內容以下
.test{
color: red;
}
複製代碼
修改index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css'
const App = () => (
<div className="test"> Hello World!! </div>
)
ReactDOM.render(<App />, document.getElementById('root')); 複製代碼
修改【webpack.common.config.js】📃
//...
rules:[
{
test: /\.(js|jsx)?$/,
// 開啓緩存
options: { cacheDirectory: true },
loader: 'babel-loader',
},
+ {
+ test: /\.css$/,
+ use: [
+ 'css-loader',
+ 'style-loader',
+ ]
+ }
]
//....
複製代碼
記得從新運行,由於webpack的配置他讀取一次,因此若是你修改了配置,須要【ctrl+c】關閉從新運行。
嘿嘿……是否是運行不了啊。
其實我是故意的,我想告訴你們一個知識點。
loader的加載順序是從右往左。這裏的編譯順序是先用css-loader將css代碼編譯,再交給style-loader插入到網頁裏面去。因此css-loader在右,style-loader在左。
雖然咱們的數組換行了,可是仔細看不難看出順序。
因此咱們只須要將他們換個位置就能夠了。代碼我就不貼了。
如今你們應該記憶很深入了吧!
你們從新【ctrl+c】關閉從新運行就好了。咱們的hello world是否是變紅啦~
說到css,說句實在話,沒幾人真的是在寫純css的吧?如今誰不是less,sass或者其餘css預處理呢?並且這些預處理的好處我就不細說了,感興趣的本身Google吧,本文用的是less(由於ant design用的也是less,哈哈,僞裝是螞蟻的一員)
在命令行輸入
npm install --save-dev less less-loader
複製代碼
less沒什麼好說的,用他確定要裝,less-loader,顧名思義,就是less的解析者。
在【webpack.common.config.js】增長
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
]
},
+ {
+ test: /\.less$/,
+ use: [
+ 'style-loader',
+ 'css-loader',
+ 'less-loader',
+ ]
+ }
複製代碼
依舊是順序問題,先解析less,把less解析成常規的css,而後再解析css,最後插入到網頁中去。
修改【index.js】引入本身寫的【.less】文件
你們從新【ctrl+c】關閉從新運行就好了。至於你寫了什麼less特性,只要有效果就好了。
說完CSS,美麗的網頁固然離不開咱們動人的圖片啦。
【file-loader】的做用是,把你的文件打包起來,和js文件放在一塊兒,這樣用戶訪問咱們的網頁的時候,其實也須要訪問咱們的url,既增長了服務器的壓力,也增長了用戶升級流量的壓力,須要去下載這個文件。
【url-loader】
若是頁面圖片較多,發不少http請求,會下降頁面性能。這個問題能夠經過url-loader解決。url-loader會將引入的圖片編碼,生成dataURl並將其打包到文件中,最終只須要引入這個dataURL就能訪問圖片了。
url-loader和file-loader兩兄弟的搭配能夠有效的減小沒必要要的url請求,由於有的圖片你要去請求url獲取,若是小的話徹底能夠用base64替代。若是圖片很大的話就用file-loader,這樣能夠減小編碼的壓力。
在命令行輸入
npm install file-loader url-loader --save-dev
複製代碼
修改【webpack.common.config.js】📃
module: {
rules: [
//...
+ {
+ test: /\.(jpg|png|gif)$/,
+ use: {
+ loader: 'url-loader',
+ options: {
+ name: '[name].[ext]', //輸出的文件名
+ outputPath: 'images/', // 輸出到dist目錄下的路徑(dist/images/)
/**
* 若是你這個圖片文件大於8192b,即8kb,那我url-loader就不用,轉而去使用file-loader,
* 把圖片正常打包成一個單獨的圖片文件到設置的目錄下,如果小於了8kb,
* 那好,我就將圖片打包成base64的圖片格式插入到bundle.js文件中,
* 這樣作的好處是,減小了http請求,可是若是文件過大,js文件也會過大,
* 得不償失,這是爲何有limit的緣由!
*/
+ limit: 8192,
+ },
+ }
+ }
]
}
複製代碼
基本上咱們的webpack能夠正常運行了,css,js,jsx均可以解析了。可是咱們須要考慮一些進階的東西,優化。
在控制檯執行如下代碼:
npm install uglifyjs-webpack-plugin --save-dev
複製代碼
在【webpack.prod.config.js】添加代碼
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
//...
optimization: {
minimizer: [
new UglifyJsPlugin({
test: /\.js(\?.*)?$/i, //測試匹配文件,
include: /\/includes/, //包含哪些文件
excluce: /\/excludes/, //不包含哪些文件
cache: false, //是否啓用文件緩存,默認緩存在node_modules/.cache/uglifyjs-webpack-plugin.目錄
parallel: true, //使用多進程並行運行來提升構建速度
//容許過濾哪些塊應該被uglified(默認狀況下,全部塊都是uglified)。
//返回true以uglify塊,不然返回false。
chunkFilter: (chunk) => {
// `vendor` 模塊不壓縮
if (chunk.name === 'vendor') {
return false;
}
return true;
}
}),
],
},
//..
};
複製代碼
其實咱們寫的代碼,有些庫的代碼是不須要每次都編譯的,最簡單的例子就是React,這個咱們幾乎每一個js文件都會用到。因此咱們能夠將它們單獨打包,這樣只須要打包一次。
修改【webpack.common.config.js】
entry: {
index: './src/index.js',
+ common: ['react', 'react-dom']
},
複製代碼
修改【webpack.prod.config.js】
const merge = require('webpack-merge'); // 版本爲4.x
// webpack-merge 5.x版本應該改成 const { merge } = require('webpack-merge');
const common = require('./webpack.common.config.js');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = merge(common, {
mode: 'production',
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html', // 打包以後的html文件名字
// 這裏有小夥伴可能會疑惑爲何不是 '../public/index.html'
// 個人理解是不管與要用的template是否是在一個目錄,都是從根路徑開始查找
template: 'public/index.html', // 以咱們本身定義的html爲模板生成,否則咱們還要到打包以後的html文件中寫script
inject: 'body',// 在body最底部引入js文件,若是是head,就是在head中引入js
minify: { // 壓縮html文件
removeComments: true, // 去除註釋
collapseWhitespace: true, // 去除空格
},
}),
new CleanWebpackPlugin()
],
optimization: {
minimizer: [
new UglifyJsPlugin({
test: /\.js(\?.*)?$/i, //測試匹配文件,
// include: /\/includes/, //包含哪些文件
// excluce: /\/excludes/, //不包含哪些文件
//容許過濾哪些塊應該被uglified(默認狀況下,全部塊都是uglified)。
//返回true以uglify塊,不然返回false。
chunkFilter: (chunk) => {
// `vendor` 模塊不壓縮
if (chunk.name === 'vendor') {
return false;
}
return true;
}
}),
cache: false, //是否啓用文件緩存,默認緩存在node_modules/.cache/uglifyjs-webpack-plugin.目錄
parallel: true, //使用多進程並行運行來提升構建速度
],
splitChunks: {
/** * 默認值是async * 拆分模塊的範圍,它有三個值async、initial和all。 * async表示只從異步加載得模塊(動態加載import())裏面進行拆分 * initial表示只從入口模塊進行拆分 * all表示以上二者都包括 */
chunks: 'all',
// minSize: 30000, // 生成chunk的最小大小(以字節爲單位)。只有大於這個數字才能夠成一個chunk
// minRemainingSize: 0, // 只有剩下一個chunk的時候纔會生效,默認是和minSize同樣的,開發的時候默認是0
// maxSize: 0, // 告訴webpack嘗試將大於maxSize字節的塊拆分爲較小的部分。
// minChunks: 1, // 拆分前必須共享模塊的最小塊數。
// maxAsyncRequests: 6, // 按需加載時最大並行請求數。
// maxInitialRequests: 4, // 入口點的最大並行請求數。入口文件
// automaticNameDelimiter: '~', // 默認狀況下,webpack將使用塊的來源和名稱生成名稱(例如vendors~main.js)。此選項使您能夠指定用於生成名稱的定界符。
cacheGroups: {
/** * 當webpack處理文件路徑時,它們始終包含/在Unix系統和\Windows上。 * 這就是爲何[\\/]在{cacheGroup}.test字段中使用in 來表示路徑分隔符的緣由。 * /或\in {cacheGroup}.test會在跨平臺使用時引發問題。 */
// defaultVendors: {
// test: /[\\/]node_modules[\\/]/, // 分塊目標
// priority: -10 // 權重
// },
// default: {
// minChunks: 2, // 最小引用
// priority: -20, // 權重
// // 若是當前塊包含已從主捆綁包中拆分出的模塊,則將重用該模塊,而不是生成新的模塊。這可能會影響塊的結果文件名。
// reuseExistingChunk: true
// },
// 上述的splitChunks全是webpack4未設置狀況下的默認值,除了chunks從【async】->【all】其餘都沒有改
// ok,咱們如今加入咱們本身想要的代碼分割
// 由於我準備加入react等業務變幻無窮而不會變的庫
common: {
test: "common", // webpack掃面的關鍵字
name: "common", // 生成的名字
enforce: true // 是否緩存
},
}
}
},
});
複製代碼
不想寫diff啦,直接CV啦。。。
爲何我須要把react提取出來,由於哪裏都須要用,並且他幾乎不可能會變,因此我特別提出來作了緩存,其他的仍是使用的默認配置(除了chunk改成了‘all’)。
Tobias Koppers@Wsokra:optimization. splitchunks. chunks: althe only option you need for vendor and commons splitting in webpackBest combine it with html-webpack-plugin or equivalent html generation18120
做者都發推特說了,那咱們也就接受吧~就改個all,而後補一下react~
再從新打包,你會發現index.bundle.js(不被緩存)的hash值變了,可是common.bundle.js(能被緩存)的hash值沒變。
js都獨立📦,那我css也要!
其實若是把CSS打包成一個文件而後讓html引用的話能夠減少html文件的大小,暗合了HTTP2的多路複用,多文件小數量。包括以前的splitChunks裏面咱們配置的react也是爲了HTTP2。
在命令行輸入:
npm install --save-dev mini-css-extract-plugin
複製代碼
修改【webpack.common.config.js】
+ const MiniCssExtractPlugin = require('mini-css-extract-plugin');
//...
module:{
rules:[
{
test: /\.css$/,
use: [
+ MiniCssExtractPlugin.loader,
- 'style-loader',
'css-loader',
]
},
],
},
+plugins: [
+ new MiniCssExtractPlugin({
+ filename: 'css/[name].[hash].css',
+ chunkFilename: 'css/[id].[hash].css',
+ }),
]
複製代碼
其實很簡單,只須要修改一下配置【wbpack.common.config.js】
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
- 'css-loader'
+ {
+ loader: 'css-loader',
+ options: {
+ // importLoaders: 1,
+ modules: true,
+ },
+ },
]
},
複製代碼
postcss 一種對css編譯的工具,相似babel對js的處理,常見的功能如: 1 . 使用下一代css語法 2 . 自動補全瀏覽器前綴 3 . 自動把px代爲轉換成rem 4 . css 代碼壓縮等等 postcss 只是一個工具,自己不會對css一頓操做,它經過插件實現功能,autoprefixer 就是其一。
安裝postcss
npm install postcss postcss-loader --save-dev
複製代碼
安裝postcss某個插件,以Autoprefixer舉例
npm install postcss-aspect-ratio-mini postcss-write-svg postcss-px-to-viewport postcss-viewport-units postcss-flexbugs-fixes postcss-preset-env cssnano --save-dev
複製代碼
在根目標新建文件【postcss.config.js】
/* eslint-disable import/no-extraneous-dependencies */
/* eslint-disable @typescript-eslint/no-var-requires */
const postcssAspectRatioMini = require('postcss-aspect-ratio-mini');
const postcssPxToViewport = require('postcss-px-to-viewport');
const postcssWriteSvg = require('postcss-write-svg');
const postcssViewportUnits = require('postcss-viewport-units');
const cssnano = require('cssnano');
const postcssPresetEnv = require('postcss-preset-env')
const postcssFlexbugsFixes = require('postcss-flexbugs-fixes')
module.exports = {
plugins: [
postcssFlexbugsFixes,
// 在這個位置加入咱們須要配置的代碼
// 在這個位置加入咱們須要配置的代碼
// 在這個位置加入咱們須要配置的代碼
postcssAspectRatioMini({}),
postcssPxToViewport({
viewportWidth: 750, // 基準寬度(通常的設計都是這個基準
viewportHeight: 1334, // 基準高度(通常的設計都是這個基準
unitPrecision: 3, // (Number) The decimal numbers to allow the REM units to grow to.
viewportUnit: 'vw', // (String) 單位
selectorBlackList: ['.list-ignore', /notTransform/], // 帶上這個單詞的就不會fix爲vw單位
minPixelValue: 1, // (Number) 最小像素
mediaQuery: false, // (Boolean) 容許在媒體查詢中轉換px。
exclude: /(\/|\\)(node_modules)(\/|\\)/,
}),
postcssWriteSvg({
utf8: false
}),
postcssPresetEnv({}),
postcssViewportUnits({
filterRule: rule => rule.selector.includes('::after')
&& rule.selector.includes('::before')
&& rule.selector.includes(':after')
&& rule.selector.includes(':before')
}),
cssnano({
"cssnano-preset-advanced": {
zindex: false,
autoprefixer: false
},
})
]
};
複製代碼
修改【webpack.common.config.js】
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
+ 'postcss-loader'
]
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader',
+ 'postcss-loader'
]
}
複製代碼
而後,修改咱們的css文件,看看咱們寫的單位爲px的有沒有被改成vw的自適應單位。
順便試一下帶有【notTransform】的是否是仍是px做爲單位。
到此,咱們的webpack配置,就算是入門了,對於webpack的配置咱們還有很長的路要走。你們加油!
若是有哪裏寫的很差或者寫錯了,歡迎你們在評論區討論。