[TOC]
## FAQ
### webpack4.x有哪些默認行為?
默認入口為`./src/index.js`
默認出口為`./dit`
默認`mode`為`production`,打包出的js文件會被壓縮
### 如何改變打包模式?
默認為`production`,
我們可以在package.json中通過給腳本添加`--development`運行,轉換成`development`模式
```
"scripts": {
"dev":webpack --development
...
```
也可以在配置文件中
```
entry:...
...
, mode: 'development'
...
```
### entry有幾種寫法?
>[danger] **注意:** 路徑必須帶上`./`
字符串的形式:單進單出
```
entry:'./src/index.js'
```
數組的形式:支持多進單出
```
entry: ['./src/a.js','./src/b.js']
```
對象的形式:支持多進多出
```javascript
entry:{
a:'./src/a.js'
,b:'./src/b.js'
}
```
### 如何控制打包出的文件的名字和路徑?
```
,output: {
filename: "./test/[name].js"
,path:path.resolve(__dirname,'dist')
}
```
我們可以通過配置output對象中的`path`來決定我們打包后輸出文件的**根路徑**。(注意這個path路徑一定是**絕對路徑**)
之所以說是根路徑,是因為我們能通過配置output對象中的`filename`來近一步控制我們的輸出路徑。
除此之外filename也決定了我們輸出文件的名字,我們還能通過在filenmae中使用`[name]`關鍵字來動態生成輸出文件的名字,動態生成的文件名和我們在entry對象中設置的名字一樣,如果entry不是個對象,那么此時輸出的文件名會默認為main。
### 如何控制html引入哪些打包后的資源?
默認`html-webpack-plugin`會引入所有打包出的資源。
但我們也可以使用HtmlWebpackPlugin中的`chunks`參數來控制我們每個html模板中想要引入的資源
```
,new HtmlWebpackPlugin({
template:'./src/index.html'
,filename:'index.html'
,chunks:['index']
})
,new HtmlWebpackPlugin({
template:'./src/index.html'
,filename:'a.html'
,chunks:['a','index']
})
```
其中new了幾個就會輸出幾個html,另外`filename`指定的是要輸出的html的文件名。
### 如何將css和less分開打包?
創建兩個實例
```
let cssExtract = new ExtractTextWebpackPlugin('css.css');
let lessExtract = new ExtractTextWebpackPlugin('less.css');
```
注冊
```
,plugins:[
...
,cssExtract
,lessExtract
...
```
配置
```
{test:/\.css$/,use:cssExtract.extract({
fallback: 'style-loader'
,use:['css-loader']
})}
,{test:/\.less$/,use:lessExtract.extract({
fallback: 'style-loader'
,use:['css-loader','less-loader']
})}
```
### 如何設置developmen或production的環境變量?如何在配置和項目文件中獲取?
```
npm i cross-env -D
```
```
"scripts": {
"build": "cross-env NODE_ENV=production webpack",
"start": "cross-env NODE_ENV=development webpack-dev-server",
...
```
這樣我們就能來在配置文件中獲取到是`development`還是 `production`
```
// webpack.config.js
let isDev = process.env.NODE_ENV === 'development';
//一頓配置操作。。。噼里啪啦,不對,是ctl+v
```
除了在配置文件中,我們也能在項目文件中拿到這環境變量
```
//使用這個插件注入一個全局的變量
...
let webpack = require('webpack');
...
, new webpack.DefinePlugin({
__DEV__: isDev
})
```
### 我的css為什么不會更新了?
出現這種情況很有可能是你用了`extract-text-webpack-plugin`,這個插件抽離出去的css文件并不支持webpack-dev-server的更新。
So,我們一般在開發的時候使用`style-loader`。
你可以根據設置的環境變量來切換使用哪種css的插入模式。
```
//實例化和注冊plugin時
, new ExtractTextWebpackPlugin({
filename: 'css/index.css'
,disable:isDev // 依據環境變量來決定是否啟用該插件
})
```
```
, use: ExtractTextWebpackPlugin.extract({
fallback: 'style-loader
...
```
### 引入路徑太長,想要簡化?想要省略后綴?想要自定義模塊查詢?
```
, resolve: {
alias: {
'bootstrap': path.resolve(__dirname, 'node_modules/bootstrap/dist/css/bootstrap.css')
}
, extensions: [' ', '.js', '.json', '.css'] //第一個放空 規定
, modules: ['node_modules', 'lib']
// , mainFields: [] //默認package.json的main是文件的入口 這里可以自定義
}
```
## 功能
### 添加html模板自動插入打包文件
```
npm i html-webpack-plugin -D
```
```
,new HtmlWebpackPlugin({
template:'./src/index.html' //用哪個html作為模板
,hash:true
,minify:{ //壓縮html
collapseWhitespace:true //去除空白
,removeAttributeQuotes:true //去除引號
}
})
```
>hash:
設置為true時,能有效防止開發時重新打包后依然引入服務器過去緩存的資源,
打包后的文件的引入路徑是這樣的
```
src="bundle.js?2baa6d527087b9fdd38d"
```
### 啟用一個自動刷新服務器
```
npm i webpack-dev-server -D
```
```
,devServer:{
contentBase:'dist' //可以在url欄中輸入對應地址訪問到dist目錄下的靜態資源
,host:'localhost'
,port:3000
,open:true // 自動彈出瀏覽器
,hot:true // 必須搭配熱替換插件 webpack自帶
}
```
### 打包前自動清理輸出目錄
```
let CleanWebpackPlugin = require('clean-webpack-plugin');
```
```
new CleanWebpackPlugin(['dist']) //['dist/a','dist/b']
```
之所以參數接收的是一個數組,就是因為它支持選擇性清空輸出目錄下文件。
### 處理css資源
```
npm i style-loader css-loader -D
```
將css樣式插入到style標簽中
```
{test:/\.css$/,use:['style-loader','css-loader']}
```
抽離到css文件并自動使用link引入
```
npm i extract-text-webpack-plugin@next -D
```
```
{test:/\.css$/,use:ExtractTextWebpackPlugin.extract({
fallback: 'style-loader'
,use:['css-loader']
})}
```
### 處理less/sass資源
```
npm i node-sass sass-loader less less-loader -D
```
```
,{test:/\.less$/,use:lessExtract.extract({
fallback: 'style-loader'
,use:['css-loader','less-loader']
})}
,{test:/\.(sass|scss)/,use:ExtractTextWebpackPlugin.extract({
fallback: 'style-loader'
,use:['css-loader','sass-loader']
})}
```
### 拷貝指定文件到輸出目錄的指定位置
一般來說是些README撒的
```
let CopyWebpackPlugin = require('copy-webpack-plugin');
...
, new CopyWebpackPlugin([{
from: './src'
, to: 'public'
}])
```
### postcss
```
npm i postcss-loader autoprefixer -D
```
```
{test:/\.css$/,use:ExtractTextWebpackPlugin.extract({
use:['css-loader','postcss-loader']
})}
```
再創建一個`postcss.config.js`文件,注冊你想要的postcss的功能
```
//postcss.config.js
module.exports = {
plugins:[require('autoprefixer')]
}
```
### es6+、react等轉譯
```
npm i babel-core babel-loader babel-preset-env babel-preset-react babel-preset-stage-0 -D
```
```
, {
test: /\.jsx?$/
, use: [
{
loader: 'babel-loader'
, options: {
presets: ['env', 'stage-0', 'react'] //順序不能亂
}
}]
, exclude: /node_modules/
, include: /src/
}
```
你也可以選擇單獨在`.babelrc`中配置你的babel `options`
```
{
"presets":["env","stage-0","react"]
}
```
### 處理圖片資源
```
npm i file-loader url-loader -D
```
```
, {
test: /\.(png|gif|jpg|jpeg)$/
, use: [
{
loader: 'url-loader'
, options: {
limit: 5 //低于5字節圖片將以base64的形式存在
, outputPath: 'images/'
}
}]
, exclude: /node_modules/
, include: /src/
}
```
圖片引用的三種形式
- 在js中引用圖片
```
let oImg = new Image();
import png from './1.png'; //如果引入了圖片 就可以把圖片進行打包,其中png不是圖片本身,而是文件的路徑
oImg.src = png; //如果不是用import引入的將不會被打包
document.body.appendChild(oImg);
```
- 在背景圖中使用
```
background:url('1.png'); //開發目錄中圖片相對css文件的路徑
```
- 直接通過路徑引用 相對 html
需要額外的包
```
npm i html-withimg-loader -D
```
```
<img src="./eg4/1.png" alt=""> //圖片相對于html模板的路徑
```
###
hotmodule
PurifyWebpack
## optimization
### 打包速度優化
#### exclude和include
```
, exclude: /node_modules/
, include: /src/
```
#### dll動態鏈接庫
一個項目中的第三方包我們大多數情況下是不需要修改的,So當項目中我們自己文件的更改導致整個項目重新打包是很消耗性能的,比如,第三方庫我們完全不需要再重新打包。
So,DllPlugin就是為了解決這個問題,它會將我們的第三方庫生成為動態鏈接庫,這樣當項目更新重新打包時候就不再需要打包第三方庫的部分,只需要引用這個動態鏈接庫即可。
首先,單獨打包一份項目中要使用的第三方庫
```
let path = require('path');
let webpack = require('webpack');
module.exports = {
entry:{
vendor:['react','react-dom']
}
, mode: 'development'
, output: {
filename: '[name].js'
, path: path.join(__dirname, 'dist')
, library: '_dll_[name]' //必須和DllPlugin中設置的name一樣
}
, plugins: [
new webpack.DllPlugin({
name:'_dll_[name]' //打包后的文件名
,path:path.resolve(__dirname,'dist','[name].manifest.json') //必須是json //打到哪去
})
]
}
```
最終會在`dist`目錄下生成兩個文件`vendor.js`和`vendor.manifest.json`。
這個時候需要我們在`index.html`中手動引入`vendor.js`
```
<script src="./vendor.js"></script> //打包后html和vendor是平級的,故這里為./vendor.js
```
然后,我們還需要在我們項目打包時引入`vendor.manifest.json`
```
,new webpack.DllReferencePlugin({
manifest:path.join(__dirname,'dist','vendor.manifest.json')
})
```
### 線上加載優化
#### splitChunks代碼分隔
```
,optimization:{
splitChunks:{
cacheGroups:{
vendor:{
test:/node_modules/ //引node_modules中的才會抽離到vendor
,chunks:'initial'
,name:'vendor'
,priority:10 //提高優先級,會先抽離vendor
}
,commons:{ //commons優先級默認比vendor高
chunks:'initial'
,name:'commons'
,minSize:0 //只要超出0字節就生產新的包
}
}
}
}
```