本文會(huì)一步一步從 webpack 安裝定欧、npm 腳本命令添加渔呵、各個(gè)插件的作用和安裝及配置一步一步說(shuō)明,如果不想看砍鸠,可以跳到文末扩氢,我會(huì)把所有安裝的插件和配置匯總放在最后。
1. 安裝 webpack 和 webpack-cli
npm install --save-dev webpack webpack-cli
新建 src 目錄爷辱,此為源文件目錄
因?yàn)榉侨职惭b录豺,webpack 沒(méi)加入全局變量,只能通過(guò)npx執(zhí)行命令
npx webpack // npx為npm 5.2后增加的命令
打包后會(huì)生成 dist 目錄饭弓,此為打包文件的目錄
├── /項(xiàng)目目錄(根目錄)
│ ├── /src(源文件目錄)
│ └── index.js
│ ├── /dist(打包文件生成目錄)
│ └── main.js
│ ├── /node_modules(包安裝目錄)
│ └── ......
│ ├── package-lock.json
│ └── package.json
2. 為 npm 添加命令
使用過(guò) vue.js 的腳手架 vue-cli 的話双饥,會(huì)常用到命令如:
npm run dev
其實(shí)這個(gè)是 vue-cli 在 npm 中配置好的。
在 package.json 的 scripts 中就可以配置腳本:
// ...
"scripts": {
"build": "webpack --config webpack.config.js",
},
// ...
上述配置會(huì)增加一個(gè)打包命令:
npm run build
3. 配置webpack
在根目錄新建 webpack.config.js 如下:
const path = require('path')
module.exports = {
entry: './src/index.js', //入口文件
output: {
filename: 'bundle.[hash].js', //默認(rèn)為main.js
path: path.resolve(__dirname,'./dist') //path為絕對(duì)路徑弟断,用node path模塊轉(zhuǎn)化
},
mode: 'development' //開(kāi)發(fā)模式
}
- entry 為入口源文件
- output 為打包后生成文件的設(shè)置兢哭,其中 filename 為生成的文件名,[hash]為隨機(jī)哈希字符串夫嗓,避免緩存迟螺。path 為打包文件生成的目錄。
- mode 為打包的模式舍咖,默認(rèn)為production(生產(chǎn)模式)矩父,會(huì)壓縮代碼。development(開(kāi)發(fā)模式)不會(huì)壓縮代碼排霉,便于閱讀窍株。
- tips:打包文件使用[hash]后,每次打包都會(huì)生成新的文件攻柠,久了會(huì)產(chǎn)生大量冗余文件球订,這個(gè)時(shí)候就需要用到 clean-webpack-plugin 來(lái)清除老版本文件。
npm i clean-webpack-plugin -D // i 等于 install, -D 等于 --save-dev
webpack.config.js 里引入
// ...
const CleanWebpackPlugin = require('clean-webpack-plugin')
module.exports = {
// ...
plugins:[ //存放插件
new CleanWebpackPlugin()
]
}
此時(shí)的 webpack.config.js 長(zhǎng)這個(gè)樣子:
const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
module.exports = {
entry: './src/index.js', //入口文件
output: {
filename: 'bundle.[hash].js', //默認(rèn)為main.js [hash]是為了避免js緩存
path: path.resolve(__dirname,'./dist') //path為絕對(duì)路徑瑰钮,用node path模塊轉(zhuǎn)化
},
mode: 'development', //開(kāi)發(fā)模式
plugins:[ //存放插件
new CleanWebpackPlugin()
]
}
現(xiàn)在冒滩,每次打包前,都會(huì)清空 dist 目錄
4. 自動(dòng)生成 html
目前打包只能生成 js 文件浪谴,每次都還要手動(dòng)的去 html 文件中引用开睡,十分不方便因苹,如果需要自動(dòng)生成 html,則要用到 html-webpack-plugin:
npm i html-webpack-plugin -D
在 src 目錄下新建模版 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>模板</title>
</head>
<body>
html
</body>
</html>
webpack.config.js 里引入
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
// ...
plugins:[
// ...
new HtmlWebpackPlugin({
template: './src/index.html', // 模板位置
filename: 'index.html', // 生成的html文件名篇恒,默認(rèn)也是index.html
minify: {
removeAttributeQuotes: true, // 刪除標(biāo)簽屬性的雙引號(hào)
collapseInlineTagWhitespace: true, // 刪除多余空格
},
hash: true // 增加hash扶檐,避免緩存
})
]
}
現(xiàn)在,每次打包胁艰,會(huì)在 dist 目錄中生成一個(gè) index.html款筑,并自動(dòng)引入 js 文件
5. 配置本地開(kāi)發(fā)服務(wù)器
本地開(kāi)發(fā)服務(wù)器可以不用每次都打包生成文件,再去看效果:
npm i webpack-dev-server -D
webpack.config.js 里引入
devServer:{ // 開(kāi)發(fā)服務(wù)器配置
port: 3000, // 端口號(hào)
progress: true, // 進(jìn)度條
contentBase: './static', // 服務(wù)默認(rèn)指向文件夾腾么,靜態(tài)資源
inline: true, // 設(shè)置為true醋虏,當(dāng)源文件改變的時(shí)候會(huì)自動(dòng)刷新
historyApiFallback: true, // 在開(kāi)發(fā)單頁(yè)應(yīng)用時(shí)非常有用,它依賴于HTML5 history API哮翘,如果設(shè)置為true,所有的跳轉(zhuǎn)將指向index.html
hot: true, // 允許熱加載
open: true // 自動(dòng)打開(kāi)瀏覽器
}
啟動(dòng)這個(gè)服務(wù)可以通過(guò)如下命令啟動(dòng)
npx webpack-dev-server
也可以在 package.json 的 scripts 腳本配置:
"scripts": {
"build": "webpack --config webpack.config.js",
"dev": "webpack-dev-server"
}
運(yùn)行
npm run dev
則自動(dòng)在瀏覽器打開(kāi)了一個(gè)服務(wù)毛秘。
到此饭寺,目錄結(jié)構(gòu) 如下:
├── /項(xiàng)目目錄(根目錄)
│ ├── /src(源文件目錄)
│ ├── index.html
│ └── index.js
│ ├── /dist(打包文件生成目錄)
│ ├── index.html
│ └── bundle.2957e949a4a4bf4735f3.js
│ ├── /node_modules(包安裝目錄)
│ └── ......
│ ├── /static(靜態(tài)資源目錄)
│ └── ......
│ ├── package-lock.json
│ ├── package.json
│ └── webpack.config.js
6. css模塊的配置
引入 css 文件,一般是在 html 中通過(guò) link 標(biāo)簽引入叫挟,或者在 js 中
require('./style.css')
因?yàn)?webpack 默認(rèn)不識(shí)別 css艰匙、less,則需要安裝各種 ** loader** :
npm i css-loader style-loader less less-loader -D
在 webpack.config.js 中加入 loader :
// ...
module.exports = {
// ...
module: {
rules: [
{
test: /\.css$/, // js 中 require css
use: ['style-loader','css-loader']
},
{
test: /\.less$/,
// 注意順序抹恳!
use: ['style-loader','css-loader','less-loader']
}
]
},
plugins:[
// 存放插件
],
devServer:{
// 開(kāi)發(fā)服務(wù)器
}
}
7. ES6 處理
目前的瀏覽器對(duì) ES6 語(yǔ)法支持都不完整员凝,需要轉(zhuǎn)化成 ES5 才能執(zhí)行:
npm install babel-loader @babel/core @babel/preset-env -D
在 webpack.config.js 中加入 :
// ...
module.exports = {
// ...
module: {
rules: [
// ...
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
},
plugins:[
// 存放插件
],
devServer:{
// 開(kāi)發(fā)服務(wù)器
}
}
es6 內(nèi)置方法轉(zhuǎn)化:
npm i @babel/plugin-transform-runtime -D
npm install --save @babel/runtime @babel/polyfill // 這個(gè)正式環(huán)境也要用
babel-runtime和babel-polyfill的作用介紹和使用
上面的 webpack.config.js 改為 :
// ...
module.exports = {
// ...
module: {
rules: [
// ...
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins:[ // es6 內(nèi)置函數(shù)轉(zhuǎn)換
'@babel/plugin-transform-runtime'
]
}
}
}
]
},
plugins:[
// 存放插件
],
devServer:{
// 開(kāi)發(fā)服務(wù)器
}
}
js文件里引入:
require('@babel/polyfill')
至此,可以打包 ES6 語(yǔ)法的文件了奋献。
8. 加載圖片健霹、音頻等資源
以圖片為例,引入情況有三種:
- css 中的背景圖片
body{
background: url('./img/bg.jpg')
}
- js中通過(guò)創(chuàng)建Image標(biāo)簽再引入:
import logo from './img/logo.jpg'
let img = new Image()
img.src = logo
- 在html標(biāo)簽中引入
<img src="./img/logo.jpg" alt="">
前兩中情況瓶蚂,需要安裝:
npm i url-loader file-loader -D
webpack.config.js 加入:
// ...
module.exports = {
// ...
module: {
rules: [
// ...
{
test: /\.(png|jpe?g|gif|m4a)$/, // 加載js img 對(duì)象糖埋、css 中的圖片、音頻等資源
use: [
{
loader: 'url-loader',
options: {
//資源大小小于等于limit值窃这,則會(huì)以base64形式加載瞳别,不會(huì)發(fā)請(qǐng)求,大于這個(gè)值則用file-loader加載
limit: 200*1024
}
}
]
}
]
},
plugins:[
// 存放插件
],
devServer:{
// 開(kāi)發(fā)服務(wù)器
}
}
在html標(biāo)簽中引入圖片需要安裝:
npm i html-withimg-loader -D
webpack.config.js 加入:
// ...
module.exports = {
// ...
module: {
rules: [
// ...
{
test: /\.html$/, // 加載 img 標(biāo)簽中的圖片
use: [
{
loader: 'html-withimg-loader',
options: {}
}
]
}
]
},
plugins:[
// 存放插件
],
devServer:{
// 開(kāi)發(fā)服務(wù)器
}
}
匯總:
安裝的插件有:
npm i --D webpack webpack-cli clean-webpack-plugin html-webpack-plugin webpack-dev-server css-loader style-loader less less-loader babel-loader url-loader file-loader html-withimg-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime
npm i --save @babel/runtime @babel/polyfill
最后 webpack.config.js 長(zhǎng)這個(gè)樣子:
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin') // 自動(dòng)清除沉余js
const HtmlWebpackPlugin = require('html-webpack-plugin') // 自動(dòng)生成 html 插件
module.exports = {
entry: './src/index.js', //入口文件
output: {
filename: 'bundle.[hash].js', // 默認(rèn)為main.js [hash]是為了避免js緩存
path: path.resolve(__dirname,'./dist') // path為絕對(duì)路徑杭攻,用node path模塊轉(zhuǎn)化
},
mode: 'development', // 開(kāi)發(fā)模式, 生產(chǎn)模式 'production' 會(huì)壓縮代碼
module: { // 加載 css less
rules: [
{
test: /\.css$/, // js 中 require css
use: ['style-loader','css-loader']
},
{
test: /\.less$/,
// 注意順序
use: ['style-loader','css-loader','less-loader']
},
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins:[ // es6 內(nèi)置函數(shù)轉(zhuǎn)換
'@babel/plugin-transform-runtime'
]
}
}
},
{
test: /\.(png|jpe?g|gif|m4a)$/, // 加載js img 對(duì)象祟敛、css 中的圖片、音頻等資源
use: [
{
loader: 'url-loader',
options: {
//圖片大小小于等于limit值兆解,則會(huì)以base64形式加載馆铁,不會(huì)發(fā)請(qǐng)求,大于這個(gè)值則用file-loader加載
limit: 200*1024
}
}
]
},
{
test: /\.html$/, // 加載 img 標(biāo)簽中的圖片
use: [
{
loader: 'html-withimg-loader',
options: {}
}
]
}
]
},
plugins:[ // 存放插件
new HtmlWebpackPlugin({
template: './src/index.html', // 模板
filename: 'index.html', // 默認(rèn)也是index.html
minify: {
removeAttributeQuotes: true, // 刪除標(biāo)簽屬性的雙引號(hào)
collapseInlineTagWhitespace: true, // 刪除多余空格
},
hash: true, // 增加hash锅睛,避免緩存
}),
new CleanWebpackPlugin()
],
devServer:{ // 開(kāi)發(fā)服務(wù)器配置
port: 3000, // 端口號(hào)
progress: true, // 進(jìn)度條
contentBase: './static', // 服務(wù)默認(rèn)指向文件夾
inline: true, // 設(shè)置為true叼架,當(dāng)源文件改變的時(shí)候會(huì)自動(dòng)刷新
historyApiFallback: true, // 在開(kāi)發(fā)單頁(yè)應(yīng)用時(shí)非常有用畔裕,它依賴于HTML5 history API,如果設(shè)置為true乖订,所有的跳轉(zhuǎn)將指向index.html
hot: true, // 允許熱加載
open: true // 自動(dòng)打開(kāi)瀏覽器
}
}
最后 package.json 長(zhǎng)這個(gè)樣子(變了的只有 scripts 部分扮饶,配置腳本):
{
"name": "audio-player",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack --config webpack.config.js",
"dev": "webpack-dev-server"
},
"author": "sparket",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.6.0",
"@babel/plugin-transform-runtime": "^7.6.0",
"@babel/preset-env": "^7.6.0",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.2.0",
"html-webpack-plugin": "^3.2.0",
"less": "^3.10.3",
"less-loader": "^5.0.0",
"style-loader": "^1.0.0",
"webpack": "^4.40.2",
"webpack-cli": "^3.3.9",
"webpack-dev-server": "^3.8.1"
},
"dependencies": {
"@babel/polyfill": "^7.6.0",
"@babel/runtime": "^7.6.0",
"file-loader": "^4.2.0",
"html-withimg-loader": "^0.1.16",
"url-loader": "^2.1.0"
}
}
參考資料:
1.http://www.reibang.com/p/99675e491ee6
2.http://www.reibang.com/p/f06e901860e
3.http://www.reibang.com/p/bacc576979fe