本文会一步一步从 webpack 安装、npm 脚本命令添加、各个插件的作用和安装及配置一步一步说明,如果不想看,可以跳到文末,我会把所有安装的插件和配置汇总放在最后。
1. 安装 webpack 和 webpack-cli
npm install --save-dev webpack webpack-cli
新建 src 目录,此为源文件目录
因为非全局安装,webpack 没加入全局变量,只能通过npx执行命令
npx webpack // npx为npm 5.2后增加的命令
打包后会生成 dist 目录,此为打包文件的目录
├── /项目目录(根目录)
│ ├── /src(源文件目录)
│ └── index.js
│ ├── /dist(打包文件生成目录)
│ └── main.js
│ ├── /node_modules(包安装目录)
│ └── ......
│ ├── package-lock.json
│ └── package.json
2. 为 npm 添加命令
使用过 vue.js 的脚手架 vue-cli 的话,会常用到命令如:
npm run dev
其实这个是 vue-cli 在 npm 中配置好的。
在 package.json 的 scripts 中就可以配置脚本:
// ...
"scripts": {
"build": "webpack --config webpack.config.js",
},
// ...
上述配置会增加一个打包命令:
npm run build
3. 配置webpack
在根目录新建 webpack.config.js 如下:
const path = require('path')
module.exports = {
entry: './src/index.js', //入口文件
output: {
filename: 'bundle.[hash].js', //默认为main.js
path: path.resolve(__dirname,'./dist') //path为绝对路径,用node path模块转化
},
mode: 'development' //开发模式
}
- entry 为入口源文件
- output 为打包后生成文件的设置,其中 filename 为生成的文件名,[hash]为随机哈希字符串,避免缓存。path 为打包文件生成的目录。
- mode 为打包的模式,默认为production(生产模式),会压缩代码。development(开发模式)不会压缩代码,便于阅读。
- tips:打包文件使用[hash]后,每次打包都会生成新的文件,久了会产生大量冗余文件,这个时候就需要用到 clean-webpack-plugin 来清除老版本文件。
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()
]
}
此时的 webpack.config.js 长这个样子:
const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
module.exports = {
entry: './src/index.js', //入口文件
output: {
filename: 'bundle.[hash].js', //默认为main.js [hash]是为了避免js缓存
path: path.resolve(__dirname,'./dist') //path为绝对路径,用node path模块转化
},
mode: 'development', //开发模式
plugins:[ //存放插件
new CleanWebpackPlugin()
]
}
现在,每次打包前,都会清空 dist 目录
4. 自动生成 html
目前打包只能生成 js 文件,每次都还要手动的去 html 文件中引用,十分不方便,如果需要自动生成 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文件名,默认也是index.html
minify: {
removeAttributeQuotes: true, // 删除标签属性的双引号
collapseInlineTagWhitespace: true, // 删除多余空格
},
hash: true // 增加hash,避免缓存
})
]
}
现在,每次打包,会在 dist 目录中生成一个 index.html,并自动引入 js 文件
5. 配置本地开发服务器
本地开发服务器可以不用每次都打包生成文件,再去看效果:
npm i webpack-dev-server -D
webpack.config.js 里引入
devServer:{ // 开发服务器配置
port: 3000, // 端口号
progress: true, // 进度条
contentBase: './static', // 服务默认指向文件夹,静态资源
inline: true, // 设置为true,当源文件改变的时候会自动刷新
historyApiFallback: true, // 在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html
hot: true, // 允许热加载
open: true // 自动打开浏览器
}
启动这个服务可以通过如下命令启动
npx webpack-dev-server
也可以在 package.json 的 scripts 脚本配置:
"scripts": {
"build": "webpack --config webpack.config.js",
"dev": "webpack-dev-server"
}
运行
npm run dev
则自动在浏览器打开了一个服务。
到此,目录结构 如下:
├── /项目目录(根目录)
│ ├── /src(源文件目录)
│ ├── index.html
│ └── index.js
│ ├── /dist(打包文件生成目录)
│ ├── index.html
│ └── bundle.2957e949a4a4bf4735f3.js
│ ├── /node_modules(包安装目录)
│ └── ......
│ ├── /static(静态资源目录)
│ └── ......
│ ├── package-lock.json
│ ├── package.json
│ └── webpack.config.js
6. css模块的配置
引入 css 文件,一般是在 html 中通过 link 标签引入,或者在 js 中
require('./style.css')
因为 webpack 默认不识别 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:{
// 开发服务器
}
}
7. ES6 处理
目前的浏览器对 ES6 语法支持都不完整,需要转化成 ES5 才能执行:
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:{
// 开发服务器
}
}
es6 内置方法转化:
npm i @babel/plugin-transform-runtime -D
npm install --save @babel/runtime @babel/polyfill // 这个正式环境也要用
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 内置函数转换
'@babel/plugin-transform-runtime'
]
}
}
}
]
},
plugins:[
// 存放插件
],
devServer:{
// 开发服务器
}
}
js文件里引入:
require('@babel/polyfill')
至此,可以打包 ES6 语法的文件了。
8. 加载图片、音频等资源
以图片为例,引入情况有三种:
- css 中的背景图片
body{
background: url('./img/bg.jpg')
}
- js中通过创建Image标签再引入:
import logo from './img/logo.jpg'
let img = new Image()
img.src = logo
- 在html标签中引入
<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 对象、css 中的图片、音频等资源
use: [
{
loader: 'url-loader',
options: {
//资源大小小于等于limit值,则会以base64形式加载,不会发请求,大于这个值则用file-loader加载
limit: 200*1024
}
}
]
}
]
},
plugins:[
// 存放插件
],
devServer:{
// 开发服务器
}
}
在html标签中引入图片需要安装:
npm i html-withimg-loader -D
webpack.config.js 加入:
// ...
module.exports = {
// ...
module: {
rules: [
// ...
{
test: /\.html$/, // 加载 img 标签中的图片
use: [
{
loader: 'html-withimg-loader',
options: {}
}
]
}
]
},
plugins:[
// 存放插件
],
devServer:{
// 开发服务器
}
}
汇总:
安装的插件有:
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 长这个样子:
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin') // 自动清除沉余js
const HtmlWebpackPlugin = require('html-webpack-plugin') // 自动生成 html 插件
module.exports = {
entry: './src/index.js', //入口文件
output: {
filename: 'bundle.[hash].js', // 默认为main.js [hash]是为了避免js缓存
path: path.resolve(__dirname,'./dist') // path为绝对路径,用node path模块转化
},
mode: 'development', // 开发模式, 生产模式 'production' 会压缩代码
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 内置函数转换
'@babel/plugin-transform-runtime'
]
}
}
},
{
test: /\.(png|jpe?g|gif|m4a)$/, // 加载js img 对象、css 中的图片、音频等资源
use: [
{
loader: 'url-loader',
options: {
//图片大小小于等于limit值,则会以base64形式加载,不会发请求,大于这个值则用file-loader加载
limit: 200*1024
}
}
]
},
{
test: /\.html$/, // 加载 img 标签中的图片
use: [
{
loader: 'html-withimg-loader',
options: {}
}
]
}
]
},
plugins:[ // 存放插件
new HtmlWebpackPlugin({
template: './src/index.html', // 模板
filename: 'index.html', // 默认也是index.html
minify: {
removeAttributeQuotes: true, // 删除标签属性的双引号
collapseInlineTagWhitespace: true, // 删除多余空格
},
hash: true, // 增加hash,避免缓存
}),
new CleanWebpackPlugin()
],
devServer:{ // 开发服务器配置
port: 3000, // 端口号
progress: true, // 进度条
contentBase: './static', // 服务默认指向文件夹
inline: true, // 设置为true,当源文件改变的时候会自动刷新
historyApiFallback: true, // 在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html
hot: true, // 允许热加载
open: true // 自动打开浏览器
}
}
最后 package.json 长这个样子(变了的只有 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.https://www.jianshu.com/p/99675e491ee6
2.https://www.jianshu.com/p/f06e901860e
3.https://www.jianshu.com/p/bacc576979fe