webpack的使用

# 什么是webpack?*

問題:為什么在 vue 中使用 npm run build 命令就可以把開發(fā)環(huán)境中的文件進(jìn)行合并?

答案:無論是 vue 還是 react、angular,使用 cli 創(chuàng)建出來的項(xiàng)目,都自動的把結(jié)構(gòu)做好了,內(nèi)部的 webpack 也都配置好了,項(xiàng)目開發(fā)完畢后,只需要執(zhí)行 build 命令,就能夠把 src 下的文件進(jìn)行打包,這個(gè)打包功能都是由 webpack 完成的,這個(gè)配置無需我們自己操作,vue、react、angular 內(nèi)部已經(jīng)整合完畢,只需要直接使用命令即可。

**如果想手動的一步一步的配置 webpack,那么可以根據(jù)下面的文檔進(jìn)行操作。**

webpack是資源加載/打包工具

```

project1/

? ? src/

? ? dist/

```

說白了,就是把開發(fā)環(huán)境src目錄中的文件,打包到生產(chǎn)環(huán)境dist目錄下。

- 在安裝一個(gè)要打包到生產(chǎn)環(huán)境的安裝包時(shí),應(yīng)使用 npm i -S,完整寫法為 npm install --save lodash

- 如果安裝一個(gè)用于開發(fā)環(huán)境的安裝包,應(yīng)使用 npm i -D,完整寫法為 npm install --save-dev lodash

> 打包指把src下那些碎片化的文件,合并到一起,生成到dist下。

> 部署指把dist目錄當(dāng)成網(wǎng)站根目錄,供別人訪問。

# 如何使用webpack?

全局安裝

```bash

npm i -g webpack webpack-cli

```

查看版本號

```bash

webpack -v? ? ? # 4.29.6

webpack-cli -v? # 3.3.0

```

創(chuàng)建項(xiàng)目目錄

```bash

mkdir project1 && cd project1

```

初始化項(xiàng)目

```bash

npm init

```

>? npm init -y (-y參數(shù)的作用是創(chuàng)建package.json時(shí)都安裝默認(rèn)的來)

局部安裝

```bash

npm i -D webpack webpack-cli

```

創(chuàng)建目錄結(jié)構(gòu)、文件和內(nèi)容:

```

project1/

package.json

src/

index.js

```

src/index.js 中的代碼:

- 在安裝一個(gè)要打包到生產(chǎn)環(huán)境的安裝包時(shí),會打包到線上去并且在線上環(huán)境能用到的,應(yīng)使用 npm i -S,完整寫法為 npm install --save lodash

- 如果安裝一個(gè)用于開發(fā)環(huán)境的安裝包,只需要在開發(fā)的時(shí)候編譯就好,線上并不需用的到,應(yīng)使用 npm i -D,完整寫法為 npm install --save-dev lodash

```javascript?

// lodash 是一個(gè)js工具庫,用來操作 object、array、number... 更方便了

import _ from 'lodash'; // npm install --save lodash

function component(){

? ? var element = document.createElement('div')

? ? element.innerHTML = _.join(['Hello', 'webpack'], ' ')

? ? return element;

}

document.body.appendChild( component() )

```

創(chuàng)建目錄結(jié)構(gòu)、文件和內(nèi)容:

```

project1/

package.json

dist/

index.html

```

dist/index.html 中的代碼:

- main.js 文件目前還不存在

- 需要通過webpack把src/index.js文件及其依賴文件lodash打包到一起

```html

<!DOCTYPE html>

<html lang="en">

<head>

? ? <meta charset="UTF-8">

? ? <meta name="viewport" content="width=device-width, initial-scale=1.0">

? ? <meta http-equiv="X-UA-Compatible" content="ie=edge">

? ? <title>Document</title>

</head>

<body>


</body>

</html>? ? ? ?

<script src="main.js"></script>

```

在命令行中執(zhí)行:

```bash

npx webpack

```

執(zhí)行 npx webpack,會將我們的腳本作為入口起點(diǎn),然后輸出為 main.js

> Node 8.2+ 提供了 npx 命令,可以運(yùn)行在初始安裝的 webpack包(package)的webpack二進(jìn)制文件

然后就可以瀏覽dist/index.html網(wǎng)頁了

# 配置文件

在項(xiàng)目根目錄下建立webpack.config.js文件

```

project1/

webpack.config.js

```

編寫代碼,配置打包內(nèi)容。

```javascript

// 在 webpack 中使用 require 引入自帶的path模塊 (CommomJS規(guī)范)

const path = require('path')

module.exports = {

? ? entry: './src/index.js',

? ? output: {

? ? ? ? filename: 'index.js',

? ? ? ? path: path.resolve(__dirname, 'dist')

? ? }

}

```

> entry描述的是入口;output描述的是出口。

命令行執(zhí)行:

```bash

npx webpack --config webpack.config.js

```

說明:根據(jù)配置頁進(jìn)行打包,入口為src/index.js,根據(jù)入口頁的相關(guān)依賴,合并到dist/index.js中。

也可以直接執(zhí)行:

```bash

webpack

```

兩個(gè)命令是等效的

# NPM腳本

考慮到用 CLI 這種方法來運(yùn)行本地的 webpack 不是特別方便,我們可以設(shè)置快捷方式。

在 package.json 文件的 scripts 對象中,增加 build 腳本,當(dāng)執(zhí)行 build 腳本時(shí),實(shí)際執(zhí)行的是 webpack 命令。

```

"scripts":{

? ? "abc" : "npx webpack --config webpack.config.js",

? ? "build": "webpack"

}

```

使用 npm run build 命令,代替之前使用的 webpack 命令。

```bash

npm run build? # npm run abc

```

# 資源管理

加載當(dāng)前項(xiàng)目所用到的其他資源

- 加載 CSS

- 加載圖片

- 加載字體

# 加載 CSS

下載在js中解析css的模塊,我們要把js和css打包到一起。

```bash

npm install -D style-loader css-loader

```

webpack.config.js 配置規(guī)則

```javascript

module.exports = {

? ? entry: ......

? ? output: {} .....

? ? module: {

? ? ? ? rules:[

? ? ? ? ? ? { test:/\.css$/, use:['style-loader', 'css-loader'] }

? ? ? ? ]

? ? }

}

```

module.rules表示使用webpack打包模塊時(shí)所定義的打包規(guī)則。

webpack打包時(shí),如果碰到的是.css結(jié)尾的文件,使用style-loader和css-loader處理。

- style-loader:將 JS 字符串生成為 style 節(jié)點(diǎn)

- css-loader:將 CSS 轉(zhuǎn)換為 CommonJS 模塊

src/style.css

```css

.hello { color:red }

```

src/index.js

```javascript

import './style.css'

function component(){

? ? // ........

? ? element.classList.add('hello')

}

```

命令行中執(zhí)行:

```bash

npm run build

```

如果想使用 scss 文件,需要安裝

> npm config set sass-binary-site http://npm.taobao.org/mirrors/node-sass

```

npm install sass-loader node-sass --save-dev

```

然后規(guī)則中配置:

```

{ test:/\.scss$/, use:['style-loader', 'css-loader', 'sass-loader'] }

```

# 加載圖片

CSS 和 JS 中的圖片如何處理?

需要安裝:

```

npm install --save-dev file-loader

```

然后在 webpack.config.js 頁面中配置規(guī)則:

```

{ test:/\.(png|svg|jpg|gif)$/, use:['file-loader'] }

```

創(chuàng)建文件及編寫代碼

```

src/

? ? images/

? ? ? ? 1.jpg

? ? ? ? 2.jpg

index.js

import img from './images/1.jpg'

var myImg = new Image();

myImg.src = img;

document.body.appendChild( myImg );

style.scss

background: url(images/2.jpg)

```

命令行執(zhí)行:

```

npm run build

```

兩張圖片會被復(fù)制到 dist 目錄下面,網(wǎng)頁能正常使用,如果想配置圖片輸出后的路徑,可以:

```

use:[{

? ? loader:'file-loader',

? ? options:{

? ? ? ? name:'[name].[ext]',

? ? ? ? outputPath:'images'

? ? }

}]

```

# 加載字體

字體這種資源需要用到 file-loader 或 url-loader

```

npm i -D url-loader

```

規(guī)則配置:(二選一)

- file-loader會保存單獨(dú)的字體文件

```

{ test: /\.(woff|woff2|eot|ttf|otf)$/, use: ['file-loader'] }

```

- url-loader會和js合并到一起

```

{ test: /\.(woff|woff2|eot|ttf|otf)$/, use: ['url-loader'] }

```

style.css 或 style.scss

```

@font-face{

? ? font-family: abc;

? ? src: url(./fonts/經(jīng)典毛筆字體.ttf) format("truetype");

}

div{ font-family:"abc" }

```

命令行

```

npm run build

```

# 多入口多出口

PC端項(xiàng)目中可能有很多個(gè)入口,比如 index.html,比如 main.html 等,瀏覽器中都可以直接訪問。

> 移動端項(xiàng)目SPA都是單頁面應(yīng)用,用一個(gè)入口就可以了,如果是傳統(tǒng)的PC端,那么需要用到很多入口頁面。

dist/index.html

```html

<script src="index.js"></script>

```

dist/main.html

```html

<script src="main.js"></script>

```

在瀏覽器中分別訪問這兩個(gè)文件,這兩個(gè)文件分別依賴的js文件,都是獨(dú)立的,這就是多入口多出口。

wepack.config.js

```javascript

entry:{

? ? index:'./src/index.js',

? ? main:'./src/main.js'

},

output:{

? ? filename:'[name].js',

? ? path:path.resolve(__dirname, 'dist')

}

```

entry描述的是入口,表示有兩個(gè)入口 ,一個(gè)名字叫做index,一個(gè)名字叫做main。

output描述的是出口,filename描述的是打包后文件的名字,[name]是關(guān)鍵字表示entry入口文件名,path表示合并后文件所在位置。

命令行:

```bash

npm run build

```

就能夠根據(jù)entry的配置打包出2個(gè)js文件了

# 插件

安裝:

```bash

npm install --save-dev html-webpack-plugin

```

webpack.config.js

```javascript

const HtmlWebpackPlugin = require('html-webpack-plugin')

entry: { ... },

plugins: [ new HtmlWebpackPlugin({title:'標(biāo)題欄內(nèi)容'}) ],

output: { ... }

```

HtmlWebpackPlugin 的作用就是在 dist 目錄下生成 index.html 文件,

我們現(xiàn)在的項(xiàng)目中存在 dist/index.html 所以命令執(zhí)行后,會將之前的文件覆蓋了,

如果項(xiàng)目中不存在 dist/index.html,那么 HtmlWebpackPlugin 也能夠根據(jù)默認(rèn)的配置把這個(gè) index 文件創(chuàng)建出來。

# 清理dist目錄

每次執(zhí)行webpack編譯時(shí),最好先把之前的內(nèi)容清理干凈,然后重新生成。

```bash

npm install clean-webpack-plugin --save-dev

```

webpack.config.js

```javascript

const { CleanWebpackPlugin } = require('clean-webpack-plugin')

plugins:[

? ? new CleanWebpackPlugin(),

? ? new HtmlWebpackPlugin...

]

```

# 錯(cuò)誤調(diào)試

webpack 是把很多個(gè)文件捆綁到一起,那么如果有段代碼出錯(cuò)了,怎么定位錯(cuò)誤?

src/print.js

把 console.log 改為 console.error 模擬一個(gè)錯(cuò)誤出來,執(zhí)行 npm run build 重新生成捆綁后的文件,瀏覽器運(yùn)行。

瀏覽器的控制臺中會報(bào)錯(cuò),因?yàn)槲覀冊L問的是生產(chǎn)環(huán)境下的代碼,所以報(bào)的是生產(chǎn)環(huán)境下的錯(cuò)誤,所以不好定位錯(cuò)誤。

webpack.config.js

```javascript

entry:{ ... },

devtool: 'inline-source-map'

```

加上 devtool 配置后,就能夠定位到錯(cuò)誤了,但要記得這僅僅是為了調(diào)試,生產(chǎn)時(shí)要關(guān)閉。

# 自動編譯和自動刷新

每次修改文件后,都需要手動 npm run build 這太麻煩了,所以可以安裝

```

npm install --save-dev webpack-dev-server

```

webpack.config.js

```javascript

devtool: 'inline-source-amp',

devServer: { contentBase: './dist' }? ? //把dist看作是一個(gè)根目錄去運(yùn)行

```

package.json

```javascript

"scripts":{

? ? "start" : "webpack-dev-server --open"

}

```

命令行運(yùn)行

```bash

npm start

```

然后直接修改 src 下的文件,在瀏覽器中瀏覽 dist 下的文件,看效果。

# 別名

可以把長的文件名配置短的別名,這樣描述依賴文件時(shí)會方便一些。

```javascript

output: {

? ? filename: '[name].bundle.js',

? ? path: path.resolve(__dirname, 'dist')

},

resolve:{

? ? alias: {

? ? ? '@': path.resolve('src'),

? ? ? '#': path.resolve('src/images'),

? ? ? 'fa': path.resolve('src/fonts/font-awesome-4.7.0/css'),

? ? }

},

```

使用別名

```javascript

import printMe from '@/print.js'

import img from '#/1.jpg';

import 'fa/font-awesome.min.css'

```

> 不能用$當(dāng)別名,修改webpack.config.js后要重新npm start

# 代理

解決跨域問題的一種方案

```javascript

devServer: {

? ? contentBase: './dist',? ??

? ? proxy:{

? ? ? ? "/api": {

? ? ? ? ? ? target: "http://www.wyyijiaqin.com",

? ? ? ? ? ? pathRewrite: { '^/api': '' },

? ? ? ? ? ? //secure: false,

? ? ? ? ? ? changeOrigin: true,

? ? ? ? }

? ? }

},

```

> 啟動 devServer ,該代理才有作用。

# 打包時(shí),代碼是否壓縮?

mode屬性可以定義打包時(shí)代碼是否壓縮。

- development 不壓縮代碼

- production 壓縮代碼,默認(rèn)

```javascript

output: {

? ? filename: '[name].bundle.js',

? ? path: path.resolve(__dirname, 'dist')

},

mode: "development"

```

# post-css

```bash

cnpm i postcss-loader -D

cnpm i autoprefixer -D? # 處理css瀏覽器兼容

```

這個(gè)模塊是用來處理css兼容的,會自動給css加上瀏覽器前綴,如-ms- -webkit- 等

**style/index.css**

```css

span{

? ? background: red;

? ? color:white;

? ? display: flex;

? ? flex: 1;

? ? transform: translate(-50%, -50%)

}

```

**index.js**

```javascript

import './style/index.css';

```

**webpack.config.js**

```

{

? ? test: /\.css$/,

? ? use: ['style-loader', 'css-loader', {

? ? ? ? loader: 'postcss-loader',

? ? ? ? options:{

? ? ? ? ? ? plugins: [

? ? ? ? ? ? ? ? require('autoprefixer')("last 100 versions")

? ? ? ? ? ? ]

? ? ? ? }

? ? }]

}

```

> require('autoprefixer')("last 100 versions") 參數(shù)改了就會出錯(cuò)。

語義:如果碰到css文件,先用style-loader和css-loader 處理,然后用postcss-loader處理,使用require引入autoprefixer模塊,處理css兼容

# 多個(gè) config 文件入口

配置獨(dú)立的 config 文件

比如我希望開發(fā)環(huán)境中,使用map,即出錯(cuò)時(shí),能夠看到錯(cuò)誤內(nèi)容,而生產(chǎn)環(huán)境下,出錯(cuò)時(shí),不希望看到出錯(cuò)的具體內(nèi)容,而且生產(chǎn)環(huán)境下的map還影響了文件的體積,所以應(yīng)該去掉。

```bash

npm install --save-dev webpack-merge

```

**通用配置 common.js**

```javascript

const path = require('path');

module.exports = {

? ? entry: {

? ? ? ? index: './src/index.js'

? ? },

? ? output: {

? ? ? ? filename: '[name].js',

? ? ? ? path: path.resolve(__dirname, 'dist')

? ? }

};

```

**開發(fā)環(huán)境的配置 dev.js**

```

const merge = require('webpack-merge');

const common = require('./common.js');

module.exports = merge(common, {

? ? devtool: 'inline-source-map',

? ? devServer: {

? ? ? ? contentBase: './dist'

? ? }

});

```

**生產(chǎn)環(huán)境的配置 prod.js**

```

const merge = require('webpack-merge');

const common = require('./common.js');

module.exports = merge(common, {

});

```

**package.json**

```

"scripts": {

? ? "start": "webpack-dev-server --open --config dev.js",

? ? "build": "webpack --config prod.js"

}

```

執(zhí)行 npm start 相當(dāng)于開啟了開發(fā)環(huán)境的服務(wù),如果出錯(cuò)了,檢查是不是某類文件類型的合并規(guī)則沒有被定義。

執(zhí)行 npm run build 表示根據(jù)開發(fā)環(huán)境中的文件,合并成生產(chǎn)環(huán)境下的文件。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容