---
title: webpack-base-study
date: 2019-06-27 15:56:22
tags: huoxiaoye
---
## 寫在前面
使用Webpack有一段時(shí)間了,但是感覺之前學(xué)的用的都比較零散昧谊,
所以在這里整理一下Webpack的使用知識(shí),從一開始的入門到進(jìn)階。
你知道如何使用webpack打包項(xiàng)目嗎?
你知道如何在React中使用模塊化的css樣式嗎隐解?
看文本文章后邪媳,嘿嘿嘿....
## 什么是webpack?
webpack 是前端的一個(gè)項(xiàng)目構(gòu)建工具,它是基于 Node.js 開發(fā)出來的一個(gè)前端工具叽唱;
當(dāng)我們?cè)陧?xiàng)目中導(dǎo)入了過多的外部文件是,或造成請(qǐng)求過程慢微宝,錯(cuò)綜復(fù)雜的依賴關(guān)系棺亭,以及全局變量污染等問題
那么,如何解決這些問題呢蟋软?請(qǐng)使用webpack
webpack 這個(gè)前端自動(dòng)化構(gòu)建工具镶摘,可以完美實(shí)現(xiàn)資源的合并、打包岳守、壓縮凄敢、混淆等諸多功能。
## webpack安裝的兩種方式
1. 運(yùn)行`npm i webpack -g`全局安裝webpack湿痢,這樣就能在全局使用webpack的命令
2. 在項(xiàng)目根目錄中運(yùn)行`npm i webpack --save-dev` 將webpack安裝到項(xiàng)目依賴中
## 初步使用webpack打包構(gòu)建列表隔行變色案例
1. 運(yùn)行`npm init`初始化項(xiàng)目涝缝,使用npm管理項(xiàng)目中的依賴包
2. 創(chuàng)建項(xiàng)目基本的目錄結(jié)構(gòu)
3. 使用`cnpm i jquery --save`安裝jquery類庫(kù)
4. 創(chuàng)建`main.js`并書寫各行變色的代碼邏輯:
```
// 導(dǎo)入jquery類庫(kù)
? ? import $ from 'jquery'
? ? // 設(shè)置偶數(shù)行背景色,索引從0開始,0是偶數(shù)
? ? $('#list li:even').css('backgroundColor','lightblue');
? ? // 設(shè)置奇數(shù)行背景色
? ? $('#list li:odd').css('backgroundColor',function(){
return "#f60"
});
```
5. 直接在頁面上引用`main.js`會(huì)報(bào)錯(cuò)拒逮,因?yàn)闉g覽器不認(rèn)識(shí)`import`這種高級(jí)的JS語法罐氨,需要使用webpack進(jìn)行處理,webpack默認(rèn)會(huì)把這種高級(jí)的語法轉(zhuǎn)換為低級(jí)的瀏覽器能識(shí)別的語法滩援;
6. ** webpack最基本的使用:**運(yùn)行`webpack 入口文件路徑 輸出文件路徑`對(duì)`main.js`進(jìn)行處理:
```
webpack src/js/main.js dist/bundle.js
```
我們每打包一次就要輸入一長(zhǎng)串的的指令栅隐,那么有沒有什么辦法可以簡(jiǎn)單實(shí)現(xiàn)打包呢,請(qǐng)往下看
## 使用webpack的配置文件簡(jiǎn)化打包時(shí)候的命令
1. 在項(xiàng)目根目錄中創(chuàng)建`webpack.config.js`
2. 由于運(yùn)行webpack命令的時(shí)候狠怨,webpack需要指定入口文件和輸出文件的路徑约啊,所以,我們需要在`webpack.config.js`中配置這兩個(gè)路徑:
```
? ? // 導(dǎo)入處理路徑的模塊
? ? var path = require('path');
? ? // 導(dǎo)出一個(gè)配置對(duì)象佣赖,將來webpack在啟動(dòng)的時(shí)候恰矩,會(huì)默認(rèn)來查找webpack.config.js,并讀取這個(gè)文件中導(dǎo)出的配置對(duì)象憎蛤,來進(jìn)行打包處理
? ? module.exports = {
? ? ? ? entry: path.resolve(__dirname, 'src/js/main.js'), // 項(xiàng)目入口文件
? ? ? ? output: { // 配置輸出選項(xiàng)
? ? ? ? ? ? path: path.resolve(__dirname, 'dist'), // 配置輸出的路徑
? ? ? ? ? ? filename: 'bundle.js' // 配置輸出的文件名
? ? ? ? }
? ? }
```
3. 這樣外傅,我們?cè)诖虬臅r(shí)候,輸入當(dāng)我們?cè)诳刂婆_(tái)直接輸入 webpack 命令執(zhí)行的時(shí)候俩檬,webpack會(huì)執(zhí)行以下步驟
? * 首先萎胰,webpack 發(fā)現(xiàn),我們并沒有通過命令的形式棚辽,給它指定入口和出口
? * webpack 就會(huì)去 項(xiàng)目的 根目錄中技竟,查找一個(gè)叫做 `webpack.config.js` 的配置文件
? * 當(dāng)找到配置文件后,webpack 會(huì)去解析執(zhí)行這個(gè) 配置文件屈藐,當(dāng)解析執(zhí)行完配置文件后榔组,就得到了 配置文件中,導(dǎo)出的配置對(duì)象
? * 當(dāng) webpack 拿到 配置對(duì)象后联逻,就拿到了 配置對(duì)象中搓扯,指定的 入口? 和 出口,然后進(jìn)行打包構(gòu)建包归;
我們想要解放自己的雙手锨推,可不可以我們?cè)?`ctrl + s`的時(shí)候,自動(dòng)打包呢?
## 實(shí)現(xiàn)webpack的實(shí)時(shí)打包構(gòu)建
1. 使用`webpack-dev-server`來實(shí)現(xiàn)代碼實(shí)時(shí)打包編譯公壤,當(dāng)修改代碼之后换可,會(huì)自動(dòng)進(jìn)行打包構(gòu)建。
2. 運(yùn)行`cnpm i webpack-dev-server --save-dev`安裝到開發(fā)依賴
3. 安裝完成之后境钟,在命令行直接運(yùn)行`webpack-dev-server`來進(jìn)行打包锦担,發(fā)現(xiàn)報(bào)錯(cuò),此時(shí)需要借助于`package.json`文件中的指令慨削,
來進(jìn)行運(yùn)行`webpack-dev-server`命令,在`scripts`節(jié)點(diǎn)下新增`"dev": "webpack-dev-server"`指令,
發(fā)現(xiàn)可以進(jìn)行實(shí)時(shí)打包缚态,但是dist目錄下并沒有生成`bundle.js`文件磁椒,這是為什么呢?因?yàn)閌webpack-dev-server`將打包好的文件放在了內(nèi)存中
+ 把`bundle.js`放在內(nèi)存中的好處是:由于需要實(shí)時(shí)打包編譯玫芦,所以放在內(nèi)存中速度會(huì)非辰郏快
+ 這個(gè)時(shí)候我們?cè)L問webpack-dev-server啟動(dòng)的`http://localhost:8080/`網(wǎng)站,發(fā)現(xiàn)是一個(gè)文件夾的面板桥帆,需要點(diǎn)擊到src目錄下医增,才能打開我們的index首頁,
? 此時(shí)引用不到bundle.js文件老虫,需要修改index.html中script的src屬性為:`<script src="../bundle.js"></script>`
+ 為了能在訪問`http://localhost:8080/`的時(shí)候直接訪問到index首頁叶骨,可以使用`--contentBase src`指令來修改dev指令,指定啟動(dòng)的根目錄:
```
"dev": "webpack-dev-server --contentBase src"
```
同時(shí)修改index頁面中script的src屬性為`<script src="bundle.js"></script>`
4. 注意:由于最新的webpack和webpack-dev-server打包報(bào)錯(cuò)祈匙,這里我使用的是webpack@3.12.0和webpack-dev-server@2.9.3
## 使用`html-webpack-plugin`插件配置啟動(dòng)頁面
由于使用`--contentBase`指令的過程比較繁瑣忽刽,需要指定啟動(dòng)的目錄,同時(shí)還需要修改index.html中script標(biāo)簽的src屬性夺欲,所以推薦大家使用`html-webpack-plugin`插件配置啟動(dòng)頁面.
html-webpack-plugin的兩個(gè)作用
* 自動(dòng)在內(nèi)存中根據(jù)指定頁面生成一個(gè)內(nèi)存的頁面
* 自動(dòng)跪帝,把打包好的(output輸出的) bundle.js 追加到頁面中去
使用步驟
1. 運(yùn)行`cnpm i html-webpack-plugin --save-dev`安裝到開發(fā)依賴
2. 修改`webpack.config.js`配置文件如下:
```
? ? // 導(dǎo)入處理路徑的模塊
? ? var path = require('path');
? ? // 導(dǎo)入自動(dòng)生成HTMl文件的插件
? ? var htmlWebpackPlugin = require('html-webpack-plugin');
? ? module.exports = {
? ? ? ? entry: path.resolve(__dirname, 'src/js/main.js'), // 項(xiàng)目入口文件
? ? ? ? output: { // 配置輸出選項(xiàng)
? ? ? ? ? ? path: path.resolve(__dirname, 'dist'), // 配置輸出的路徑
? ? ? ? ? ? filename: 'bundle.js' // 配置輸出的文件名
? ? ? ? },
? ? ? ? plugins:[ // 添加plugins節(jié)點(diǎn)配置插件
? ? ? ? ? ? new htmlWebpackPlugin({
? ? ? ? ? ? ? ? template:path.resolve(__dirname, 'src/index.html'),//模板路徑
? ? ? ? ? ? ? ? filename:'index.html'//自動(dòng)生成的HTML文件的名稱
? ? ? ? ? ? })
? ? ? ? ]
? ? }
```
3. 修改`package.json`中`script`節(jié)點(diǎn)中的dev指令如下:
```
"dev": "webpack-dev-server"
```
4. 將index.html中script標(biāo)簽注釋掉,因?yàn)閌html-webpack-plugin`插件會(huì)自動(dòng)把bundle.js注入到index.html頁面中些阅!
## 實(shí)現(xiàn)自動(dòng)打開瀏覽器伞剑、熱更新和配置瀏覽器的默認(rèn)端口號(hào)
**注意:熱更新在JS中表現(xiàn)的不明顯,在CSS身上表現(xiàn)明顯市埋!**
### 方式1:
+ 修改`package.json`的script節(jié)點(diǎn)如下黎泣,其中`--open`表示自動(dòng)打開瀏覽器,`--port 4321`表示打開的端口號(hào)為4321腰素,`--hot`表示啟用瀏覽器熱更新:
```
"dev": "webpack-dev-server --hot --port 4321 --open"
```
### 方式2:
1. 修改`webpack.config.js`文件聘裁,新增`devServer`節(jié)點(diǎn)如下:
```
devServer: { // 這是配置 dev-server 命令參數(shù)的第二種方法,相對(duì)來說弓千,這種方法麻煩一些
? ? open: true, // 自動(dòng)打開瀏覽器
? ? port: 3000, // 設(shè)置啟動(dòng)時(shí)候的運(yùn)行端口
? ? contentBase: 'src', // 指定托管的根目錄
? ? hot: true
? },
```
2. 在頭部引入`webpack`模塊:
```
var webpack = require('webpack');
```
3. 在`plugins`節(jié)點(diǎn)下新增:
```
new webpack.HotModuleReplacementPlugin()
```
## 使用webpaack處理css文件和高級(jí)js語法
webpack 處理第三方文件類型的過程:
1. 發(fā)現(xiàn)這個(gè) 要處理的文件不是JS文件衡便,然后就去 配置文件中,查找有沒有對(duì)應(yīng)的第三方 loader 規(guī)則
2. 如果能找到對(duì)應(yīng)的規(guī)則洋访, 就會(huì)調(diào)用 對(duì)應(yīng)的 loader 處理 這種文件類型镣陕;
3. 在調(diào)用loader 的時(shí)候,是從后往前調(diào)用的姻政;
4. 當(dāng)最后的一個(gè) loader 調(diào)用完畢呆抑,會(huì)把 處理的結(jié)果,直接交給 webpack 進(jìn)行 打包合并汁展,最終輸出到? bundle.js 中去
### 使用webpack打包c(diǎn)ss文件
1. 運(yùn)行`cnpm i style-loader css-loader --save-dev`
2. 修改`webpack.config.js`這個(gè)配置文件:
```
module: { // 用來配置第三方loader模塊的
? ? ? ? rules: [ // 文件的匹配規(guī)則
? ? ? ? ? ? { test: /\.css$/, use: ['style-loader', 'css-loader'] }//處理css文件的規(guī)則
? ? ? ? ]
? ? }
```
3. 注意:`use`表示使用哪些模塊來處理`test`所匹配到的文件鹊碍;`use`中相關(guān)loader模塊的調(diào)用順序是從后向前調(diào)用的厌殉;
### 使用webpack打包less文件
1. 運(yùn)行`cnpm i less-loader less -D`
2. 修改`webpack.config.js`這個(gè)配置文件:
```
{ test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] },
```
### 使用webpack打包sass文件
1. 運(yùn)行`cnpm i sass-loader node-sass --save-dev`
2. 在`webpack.config.js`中添加處理sass文件的loader模塊:
```
{ test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }
```
### 使用webpack處理css中的路徑
1. 運(yùn)行`cnpm i url-loader file-loader --save-dev`
2. 在`webpack.config.js`中添加處理url路徑的loader模塊:
```
{ test: /\.(png|jpg|gif)$/, use: 'url-loader' }
```
3. 可以通過`limit`指定進(jìn)行base64編碼的圖片大小侈咕;只有小于指定字節(jié)(byte)的圖片才會(huì)進(jìn)行base64編碼:
```
{ test: /\.(png|jpg|gif)$/, use: 'url-loader?limit=43960' },
```
### 使用babel處理高級(jí)JS語法
1. 運(yùn)行`cnpm i babel-core babel-loader babel-plugin-transform-runtime --save-dev`安裝babel的相關(guān)loader包
2. 運(yùn)行`cnpm i babel-preset-es2015 babel-preset-stage-0 --save-dev`安裝babel轉(zhuǎn)換的語法
3. 在`webpack.config.js`中添加相關(guān)loader模塊公罕,其中需要注意的是,一定要把`node_modules`文件夾添加到排除項(xiàng):
```
{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }
```
4. 在項(xiàng)目根目錄中添加`.babelrc`文件耀销,并修改這個(gè)配置文件如下:
```
{
? ? "presets":["es2015", "stage-0"],
? ? "plugins":["transform-runtime"]
}
```
5. 注意:語法插件`babel-preset-es2015`可以更新為`babel-preset-env`楼眷,它包含了所有的ES相關(guān)的語法;
## 在React中使用模塊化的css
寫在最后熊尉,學(xué)過vue的同學(xué)都知道罐柳,我們可以在 <style scoped="scoped"></style> 來設(shè)置局部的css樣式
那么,在react中如何實(shí)現(xiàn)局部的css樣式呢狰住?
1. 在webpack.config.js中為css-loader啟用模塊化: css-loader?modules&localIdentName=[name]_[local]-[hash:8]
2. 在js 文件中引入樣式
```
import indexStyle from 'Index.css'`
// 此時(shí) indexStyle 是一個(gè)對(duì)象张吉,
// indexStyle = {
// title : '亂碼1',
box : '亂碼2'......
// }
export default function index(props) {
render(){
return (
<div className={indexStyle.box}>
? <h1 className={indexStyle.title}>XXXXXX</h1>
? <h3 className={indexStyle.body}>XXXXXX</h3>
</div>
)
}
}
```
注意
```css
/* 注意:當(dāng)啟用 CSS 模塊化之后,這里所有的類名转晰,都是私有的芦拿,
如果想要把類名設(shè)置成全局的一個(gè)類,可以把這個(gè)類名查邢,用 :global() 給包裹起來 */
/* 當(dāng)使用 :global() 設(shè)置了全局的 類樣式之后蔗崎,這個(gè)類不會(huì)被重命名 */
/* 只有私有的類才會(huì)被重命名 */
:global(.title){
? color:red;
? text-align: center;
}
```