了解webpack
1 webpack
- webpack是模块打包器
- 所有资源文件会当做模块处理
- 它将根据模块的依赖关系进行静态分析,生成对应的静态资源
2 核心概念
- Entry: 入口文件指示webpack使用了哪些模块,来作为构建其内部依
赖图的开始。 - Output:告诉 webpack 在哪里输出它所创建的打包文件,以及如何
命名这些文件。 - Loader:让 webpack 能够去处理那些非 JavaScript 文件(webpack
自身只能解析 JavaScript)。 - Plugins:插件则可以用于执行范围更广的任务。插件的范围包括,
从打包优化和压缩,一直到重新定义环境中的变量等。 - Mode:模式,有生产模式production和开发模式development。
前期准备
1 初始化项目
执行以下命令:
mkdir webpack-demo
cd webpack-demo
npm init -y
npm install webpack webpack-cli --save-dev
2 创建目录及文件
main.js为入口文件,src为开发中具体代码。
webpack-demo
├── dist
│ └── index.html
├── main.js
├── package-lock.json
├── package.json
├── src
│ └── page
│ └── index.js
3 安装cross-env 可配置多个环境变量
npm install cross-env --save-dev
4 修改package.json
修改安装包是私有的(private),并且移除 main 入口。防止发布你的代码。
{
"name": "webpack-demo",
"version": "1.0.0",
"description": "",
+ "private": true,
- "main": "index.js",
"scripts": {
-"test": "echo \"Error: no test specified\" && exit 1",
+"dev": "cross-env NODE_ENV=development webpack --config build/webpack.config.js",
+"build": "cross-env NODE_EAN=production webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12"
}
}
5 增加webpack配置文件 webpack.config.js
创建webpack.config.js,配置webpack。
webpack-demo
├── build
│ └── webpack.config.js
├── dist
│ └── index.html
├── main.js
├── package-lock.json
├── package.json
├── src
│ └── page
│ └── index.js
webpack.config.js配置如下:
const path = require('path');
module.exports = {
mode: 'development',
entry: './main.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, '..', 'dist')
}
};
6 入口文件main.js编写代码
document.write('Hi~~~');
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webpack</title>
<script src="bundle.js"></script>
</head>
<body>
</body>
</html>
7 测试打包
npm run dev
打包结果如下:
Hash: 6c2d1c4815da9f363f24
Version: webpack 4.43.0
Time: 82ms
Built at: 2020-06-30 4:31:46 PM
Asset Size Chunks Chunk Names
bundle.js 3.76 KiB main [emitted] main
Entrypoint main = bundle.js
[./main.js] 24 bytes {main} [built]
8 浏览器运行
浏览器运行index.html,显示“Hi~~~”。
分离生产环境和生产环境
1 拆分文件
修改webpack.config.js为webpack.common.js
增加webpack.dev.js
增加webpack.prod.js
webpack-demo
├── build
│ ├── webpack.common.js
│ ├── webpack.dev.js
│ └── webpack.prod.js
├── main.js
├── package-lock.json
├── package.json
├── src
│ └── page
│ └── index.js
2 修改package.json的配置
"scripts": {
"dev": "cross-env NODE_ENV=development webpack --config build/webpack.dev.js",
"build": "cross-env NODE_ENN=production webpack --config build/webpack.prod.js"
}
3 编译前自动清空dist目录、从html模板自动生成最终html、安装webpack-merge插件进行拆分
npm install clean-webpack-plugin --save-dev
npm install html-webpack-plugin --save-dev
npm install webpack-merge --save-dev
4 修改配置文件
webpack.common.js修改如下:
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, '..', 'dist')
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
filename: path.resolve(__dirname, '..', 'dist/index.html'),
template: 'index.html'
})
]
};
webpack.dev.js文件修改如下:
const common = require('./webpack.common');
const merge = require('webpack-merge');
module.exports = merge(common, {
mode: 'development'
});
webpack.prod.js文件修改如下:
const common = require('./webpack.common');
const merge = require('webpack-merge');
module.exports = merge(common, {
mode: 'production'
});
5 增加html文件作为模板
文件目录以及html文件内容修改如下:
webpack-demo
├── build
│ ├── webpack.common.js
│ ├── webpack.dev.js
│ └── webpack.prod.js
├── dist
│ ├── bundle.js
│ └── index.html
+├── index.html
├── main.js
├── package-lock.json
├── package.json
├── src
│ └── page
│ └── index.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webpack</title>
</head>
<body>
</body>
</html>
6 测试打包
执行 npm run dev 可以看到dist目录下打包文件以及自动生成的index.html文件,浏览器打开dist下index.html文件,可以看到输出Hi~~~。
搭建开发环境的热更新服务器
搭建开发环境下基于node.js的服务器,实现在修改代码时不用刷新即可自动热更新页面。安装 npm install webpack-dev-server --save-dev,
修改package.json文件,如下:
"scripts": {
"dev": "cross-env NODE_ENV=development webpack --config build/webpack.dev.js",
"build": "cross-env NODE_ENV=production webpack --config build/webpack.prod.js",
+ "server": "cross-env NODE_ENV=development webpack-dev-server --open --config build/webpack.dev.js"
},
修改webpack.dev.js文件如下:
const common = require('./webpack.common');
const merge = require('webpack-merge');
module.exports = merge(common, {
mode: 'development',
devServer: {
contentBase: './dist',
port: 8080,
hot: true
}
});
执行npm run server,会在本地启动一个nodejs的web服务,浏览器会自动打开http://localhost:8080/。输出内容 Hi~~~。这时修改main.js文件,页面会自动更新。
7 使用source-map追踪源代码错误
在编译生成的dist目录中,js代码已被重新混淆,如果出现错误,无法将错误正确定位到原始代码的对应位置,这样不方便调试生成环境的代码。如果需要精确调试生产环境代码,可通过source-map实现。
inline-source-map: 将source map 转换为 DataUrl 后添加到页面的js中,生成的js文件较大(不推荐)。
source-map: 生成对应的map文件,js较小(推荐)。
修改webpack.prod.js如下:
const common = require('./webpack.common');
const merge = require('webpack-merge');
module.exports = merge(common, {
mode: 'production',
devtool: 'source-map'
});
8 兼容ES6
npm install babel-loader @babel/core @babel/preset-env --save-dev
webpack.common.js文件增加babel-loader,如下:
output: ...
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
},
plugins: ...
9 加载css和less
npm install style-loader css-loader --save-dev
npm install less-loader less --save-dev
新加入index.css文件,内容如下:
webpack-demo
├── build
│ ├── webpack.common.js
│ ├── webpack.dev.js
│ └── webpack.prod.js
├── dist
├── index.html
├── main.js
├── package-lock.json
├── package.json
├── src
+│ ├── css
+│ │ └── index.less
│ └── page
│ └── index.js
index.less文件加入以下代码:
body{
background: gainsboro;
}
webpack.common.js增加loader:
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader'
]
},
]
}
执行npm run server 就会看见背景颜色为灰色,样式代码会直接打包插入到html文件中,控制台查看元素,可以看到以下代码。
<style>
body {
background: gainsboro;
}
</style>
10 分离样式到css文件
上面打包之后的样式并没有用link方式引入,现在我们想把样式通过link方式引入。npm install mini-css-extract-plugin --save-dev,修改webpack.common.js文件如下:
module: {
rules: [
...
{
test: /\.css$/,
use: [
// 'style-loader',
// 将原来的style-loader替换,可以通过link方式引入
MiniCssExtractPlugin.loader,
'css-loader'
]
},
{
test: /\.less$/,
use: [
// 'style-loader',
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader'
]
},
]
},
plugins: [
...
new MiniCssExtractPlugin({
filename: path.posix.join('css/[name].css'),
chunkFilename: path.posix.join('css/[name].[chunkhash].css')
})
]
执行 npm run dev 可以看到打包文件dist下有css文件夹 mian.css。
控制台可以看到引入方式为link引入:
<link href="css/main.css" rel="stylesheet">
11 还可以加入其它loader
例如 图片、字体等。