目錄
- 概述
- Big changes
- 載入loader方法總結
- 開發必備的loader&plugins
- 載入bootstrap&jquery
- 優化向prd進發
- 未完待續
概述
本月迎來了 v4 正式版的釋出,本文用於學習新特性和總結開發必用plugin & loader,從dev到prd,走你~
Big changes
- Environment
- Node.js 4 is no longer supported. Source Code was upgraded to a higher ecmascript version.
- Usage
- You have to choose (mode or --mode) between two modes now: production or development
本次新版本中引入了 mode 配置項,開發者可在 none,development(開發 ) 以及 production(產品)三種模式間選擇。該配置項預設情況下預設使用 production 模式。
- development 模式給你極致的開發體驗,包含瀏覽器除錯相關工具,極快的增量編譯,豐富全面的報錯資訊...
- production 模式則包含大量發版優化,程式碼壓縮,絲般潤滑的執行時優化,開發相關程式碼的排除,易用,etc.
- none 不使用預設,等於老版本中全部自己配置的原始狀態。
eg:
webpack --mode development
複製程式碼
- Usage
- Some Plugin options are now validated
- CLI has been move to webpack-cli, you need to install webpack-cli to use the CLI
- The ProgressPlugin (--progress) now displays plugin names At least for plugins migrated to the new plugin system
新版中將 webpack 命令列工具拆分到單獨的倉庫中,所以需要額外安裝 webpack-cli。
npm init -y //初始化專案
npm install webpack webpack-cli -D //安裝webpack webpack-cli 依賴
npx webpack --mode development // npx可以直接執行node_modules/.bin目錄下面的命令
或者通過配置package.json的script build
"scripts": {
"build": "webpack --mode development",
},
複製程式碼
載入loader方法總結
- use
module: {
rules:[
{
test: /\.css$/,
use: ['style-loader','css-loader']
}
]
}
複製程式碼
css-loader用來解析處理CSS檔案中的url路徑,
要把CSS檔案變成一個模組 多個loader是有順序要求的,從右往左寫,因為轉換的時候是從右往左轉換
此外掛先用css-loader處理一下css檔案,再用style-loader把CSS檔案變成style標籤插入head中
- loader
module: {
rules:[
{
test: /\.css$/,
loader: ["style-loader", "css-loader"]
},
]
}
複製程式碼
- use+loader
module: {
rules:[
{
test: /\.css$/,
use:[
{ loader:"style-loader"},
{
loader: 'css-loader',
options: {sourceMap: true}
}
]
}
]
}
複製程式碼
這三種loader的寫法,最後打包的結果相同
loader中的options配置項可以用"?"跟在載入器後面
eg:
{
test: /\.jpeg$/,
use: 'url-loader?limit=1024&name=[path][name].[ext]&outputPath=img/&publicPath=output/',
}
複製程式碼
為以下配置的簡寫
{
test: /\.jpeg$/,
use: {
loader:'url-loader',
options:{
limit:1024,
name:[path][name].[ext],
outputPath:img/
publicPath:output/'
}
}
}
複製程式碼
載入bootstrap&jquery
(1)載入bootstrap
要在模組中引入bootstrap需要在js中加入
import 'bootstrap/dist/css/bootstrap.css'
複製程式碼
但是這樣相對麻煩,我們可以做相關修改,將這句程式碼簡化成
import 'bootstrap'
複製程式碼
簡化方法如下:
-
在webpack中配置別名alias,可以加快webpack查詢模組的速度
-
每當引入bootstrap模組的時候,它會直接引入bootstrapPath,而不需要從node_modules資料夾中按模組的查詢規則查詢
-
不需要webpack去解析bootstrap檔案
const bootstrap=path.join(__dirname,'node_modules/bootstrap/dist/css/bootstrap.css')
resolve: {
+ alias: {
+ 'bootstrap': bootstrap
+ }
},
複製程式碼
安裝依賴
npm i bootstrap url url-loader style-loader css-loader --save
複製程式碼
在webpack.js中配置bootstrap中css 圖片 字型等檔案的解析依賴
loaders: [
{ test: /\.css$/, loader: 'style-loader!css-loader' },
{ test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file" },
{ test: /\.(woff|woff2)$/, loader:"url?prefix=font/&limit=5000" },
{ test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/octet-stream" },
{ test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=image/svg+xml" }
]
複製程式碼
(2)如果需要使用bootstrap的js外掛的話,就必須首先引入jquery。引用jquery的一個方法是使用webpack外掛。
首先安裝jquery:
npm i jquery
複製程式碼
在webpack中用外掛裝入jquery
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
複製程式碼
在入口檔案內加入程式碼來做驗證:
$("body").append("<div>hello world</div>")
複製程式碼
開發必備的loader&plugins
- css-loader
- babel-loader
講ES6程式碼轉換為ES5
{
test: /\.js/,
use: {
loader: 'babel-loader',
query: {
presets: ["env", "stage-0", "react"]
}
}
},
複製程式碼
babel-loader的預設可以新增在query中,也可以在專案根目錄新增 .babelrc 檔案
.babelrc
{
"presets": [
"env",
"stage-0",
"react"
]
}
複製程式碼
- html-webpack-plugin
外掛的基本作用就是生成html檔案。原理很簡單:
將 webpack中
entry
配置的相關入口thunk 和extract-text-webpack-plugin
抽取的css樣式 插入到該外掛提供的template
或者templateContent
配置項指定的內容基礎上生成一個html檔案,具體插入方式是將樣式link
插入到head
元素中,script
插入到head
或者body
中。
const HtmlWebpackPlugin = require('html-webpack-plugin');
new HtmlWebpackPlugin({
template: './src/index.html',//指定產的HTML模板
filename: `index.html`,//產出的HTML檔名
title: 'index',
hash: true,// 會在引入的js里加入查詢字串避免快取,
minify: {
removeAttributeQuotes: true
}
}),
複製程式碼
可以用 cnpm search html-webpack-plugin 查詢想用loader的用法
- less-loader sass-loader
優化向prd進發
- 提取公共的css程式碼
它會將所有的入口 chunk(entry chunks)中引用的 *.css,移動到獨立分離的 CSS 檔案。因此,你的樣式將不再內嵌到 JS bundle 中,而是會放到一個單獨的 CSS 檔案(即 styles.css)當中。 如果你的樣式檔案大小較大,這會做更快提前載入,因為 CSS bundle 會跟 JS bundle 並行載入。
npm i extract-text-webpack-plugin@next -D
複製程式碼
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
let cssExtract = new ExtractTextWebpackPlugin({
filename: 'css/css.css',
allChunks: true
});
複製程式碼
module:{
rules:[
{
test: /\.css$/,//轉換檔案的匹配正則
loader: cssExtract.extract({
use: ["css-loader?minimize"]
})
},
]
}
plugins:[
...... ,
+ cssExtract
]
複製程式碼
- 儘量減少檔案解析,用resolve配置檔案解析路徑,include
rules: {
test: /\.js$/,
loader:'babel-loader',
include: path.resolve(__dirname, 'src'),//只轉換或者編譯src 目錄 下的檔案
exclude: /node_modules/ //不要解析node_modules
}
複製程式碼
- resolve.mainFields
WebpackTest
|
|
| - src
| | - index.js
|
| - lib
| | - fetch
| |
| browser.js
| node.js
| package.json
|
| - webpack.config.js
複製程式碼
當從 npm 包中匯入模組時(例如,引入lib下的庫),此選項將決定在 package.json 中使用哪個欄位匯入模組。根據 webpack 配置中指定的 target 不同,預設值也會有所不同。
package.json
lib資料夾下的package.json中配置相對應模組的key
{
"name": "fetch",
"version": "1.0.0",
"description": "",
"node": "./node.js",
"browser": "./browser.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
複製程式碼
webpack.config.js
在resolve解析物件中,加入lib的路徑
resolve: {
extensions: ['.js', '.json'],
mainFields: ['main', 'browser', 'node'],
modules: [path.resolve('node_modules'), path.resolve('lib')]
}
複製程式碼
index.js
這樣在index.js中引用第三方庫時,會去查詢modules下的路徑中是否配置了所需的檔案,知道在package.json中找到mainFields中的key對應檔案,停止。
let fetch = require('fetch');
console.log(fetch);
複製程式碼
打包後 console.log出的物件
如果交換mainFields中的key順序
mainFields: ['main', 'node','browser']
複製程式碼
打包後 console.log出的物件,因為找到了key=node對應的檔案就停止了查詢
- DllReferencePlugin
這個外掛是在 webpack 主配置檔案中設定的, 這個外掛把只有 dll 的 bundle(們)(dll-only-bundle(s)) 引用到需要的預編譯的依賴。
新建webpack.react.config.js
const path = require('path');
const webpack = require('webpack')
module.exports = {
entry: {
react: ['react', 'react-dom']
},
output: {
path: path.join(__dirname, 'dist'),// 輸出動態連線庫的檔名稱
filename: '[name]_dll.js',
library: '_dll_[name]'//全域性變數的名字,其它會從此變數上獲取到裡面的模組
},
// manifest 表示一個描述檔案
plugins: [
new webpack.DllPlugin({
name: '_dll_[name]',
path: path.join(__dirname, 'dist', 'manifest.json')//最後打包出來的檔案目錄和名字
})
]
}
複製程式碼
在entry入口寫入要打包成dll的檔案,這裡把體積較大的react和react-dom打包
output中的關鍵是library的全域性變數名,下文詳細說明dll&manifest工作原理
複製程式碼
打包dll檔案
webpack --config webpack.react.config.js --mode development
複製程式碼
打包出來的manifest.json節選
打包出來的react_dll.js節選
可見manifest.json中的 name值就是
output:{
library:_dll_react
}
複製程式碼
manifest.json就是借書證,_dll_react就像圖書館書籍的條形碼,為我們最終找到filename為react_dll.js的參考書
使用“參考書”
在webpack.config.js中加入“借書證”
new webpack.DllReferencePlugin({
manifest: path.join(__dirname, 'dist', 'manifest.json')
})
複製程式碼
再執行
webpack --mode development
複製程式碼
打包速度顯著變快
打包後的main.js中,react,react-dom.js也打包進來了,成功~
import React from 'react';\n//import ReactDOM from 'react-dom';
複製程式碼
(function(module, exports, __webpack_require__) {
"use strict";
eval("\n\n//import name from './base';\n//import React from 'react';\n//import ReactDOM from 'react-dom';\n//import ajax from 'ajax';\n//let result = ajax('/ajax');\n\n//ReactDOM.render(<h1>{result}</h1>, document.getElementById('root'));\n// fetch fetch.js fetch.json fetch資料夾\n//let fetch = require('fetch');\n//console.log(fetch);\n//let get = require('../dist/bundle.js');\n//get.getName();\nconsole.log('hello');\n\nvar name = 'zfpx';\nconsole.log(name);\nif (true) {\n var s = 'ssssssssssssssssssssssss';\n console.log(s);\n console.log(s);\n console.log(s);\n console.log(s);\n}\n\n//# sourceURL=webpack:///./src/index.js?");
/***/ })
/******/ });
複製程式碼
未完待續
- webpack.ProvidePlugin
- 拷貝靜態資源
- 壓縮css(npm i -D purifycss-webpack purify-css)