bundle assets /images /script /style 打包静态资源、图片、脚本文件、样式文件
webpack是现代JavaScript应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。vue/react的脚手架基于webpack。
webpack.config.js
entry 配置入口资源
output 配置编译后的资源
module 资源处理
resolve 配置资源别名/扩展名等
plugins 插件,比loader更强大
loader 转换器
devServer 开发服务器
mode 模式(开发环境、生产环境)
Webpack 4 Tutorial: from 0 Conf to Production Mode
webpack4-用之初体验,一起敲它十一遍 这篇作者写的很棒,可以重点看看
配置 webpack4 踩了很多坑,下面对我遇到的情况做一些总结。
- scope hoisting是把公共的部分提取出来,让编译后的代码更清爽。
- tree shaking是把没有用到的代码删掉,光配tree shaking还不行,还得配置压缩才可以生效。
这是简单的demo,感兴趣的可以去看看 https://github.com/sunshineying/webpack4demo
1、全局安装webpack webpack-cli
npm install webpack -g
npm install webpack-cli -g
webpack -v 查看版本号
2、webpack4不再需要配置入口资源,默认'./src/index.js'。
也不需要配置编译后的资源,即出口,默认'./dist/main.js'。
3、webpack常见的模式有两个配置文件
一个典型的项目可能有:
用于开发的配置文件,用于定义webpack开发服务器和其他内容。
用于生产的配置文件,用于定义UglifyJSPlugin、sourcemaps等。
虽然更大的项目可能仍然需要两个文件,但在webpack 4中,您可以通过没有任何配置的方式获得。
- 生产模式允许所有类型的优化,包括压缩、范围提升等
- 开发模式是为速度而优化的,提供一个未压缩的bundle
4、在package.json里配置,覆盖默认的entry/output
"scripts": {
"dev": "webpack --mode development ./foo/src/js/index.js --output ./foo/main.js",
"build": "webpack --mode production ./foo/src/js/index.js --output ./foo/main.js"
}
是不是觉得零配置比较鸡肋?建议仍在配置文件中使用entry、output。下面讲讲多个入口打包的实现方式:
多入口文件
- 没有关系的但是要打包到一起去的,可以写一个数组,实现多个文件打包
- 每一个文件都单独打包成一个文件
let path = require('path');
module.exports = {
// 1.写成数组的方式就可以打出多入口文件,不过这里打包后的文件都合成了一个
// entry: ['./src/index.js', './src/login.js'],
// 2.真正实现多入口和多出口需要写成对象的方式
entry: {
index: './src/index.js',
login: './src/login.js'
},
output: {
// 1. filename: 'bundle.js',
// 2. [name]就可以将出口文件名和入口文件名一一对应
filename: '[name].js', // 打包后会生成index.js和login.js文件
path: path.resolve('dist')
}
}
5、用babel编译es6
使用babel-loader将es6、es7转换为es5
npm install babel-core babel-loader babel-preset-env -D
.babelrc文件
{
"presets": [
"env"
]
}
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
}
};
也可以在使用babel-loader时不用webpack.config.js配置文件,不推荐这种做法
"scripts": {
"dev": "webpack --mode development --module-bind js=babel-loader",
"build": "webpack --mode production --module-bind js=babel-loader"
}
6、设置react
npm install react react-dom -D
npm i babel-preset-react -D
.babelrc文件
{
"presets": ["env", "react"]
}
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
}
};
7、配置Html模板
通过一个模板实现打包出引用好路径的html
首先安装插件
npm i html-webpack-plugin html-loader -D
在 webpack 的配置中 loader 有两个目标:
test
属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。use
属性,表示进行转换时,应该使用哪个 loader。
webpack.config.js
const path = require('path');
// 插件都是一个类,所以我们命名的时候尽量用大写开头
const HtmlWebPackPlugin = require("html-webpack-plugin");
module.exports = {
entry: './src/index.js',
output: {
// 添加hash可以防止文件缓存,每次都会生成5位的hash串
filename: 'bundle.[hash:5].js',
path: path.resolve('dist')
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: [{
loader: "html-loader",
options: { minimize: true }
}]
}
]
},
plugins: [
// 通过new一下这个类来使用插件
new HtmlWebPackPlugin({
// 用哪个html作为模板
// 在src目录下创建一个index.html页面当做模板来用
template: "./src/index.html",
filename: "./index.html",
hash: true, // 会在打包好的bundle.js后面加上hash串
})
]
};
npm run build 查看./dist文件夹,已生成html文件(没有任何变化,只是自动注入了js)。不需要将js包含在HTML文件中,bundle会被自动注入。
多页面配置
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// 多页面开发,配置多页面
entry: {
index: './src/index.js',
login: './src/login.js'
},
// 出口文件
output: {
filename: '[name].js',
path: path.resolve('dist')
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
chunks: ['index'] // 对应关系,index.js对应的是index.html
}),
new HtmlWebpackPlugin({
template: './src/login.html',
filename: 'login.html',
chunks: ['login'] // 对应关系,login.js对应的是login.html
})
]
}
8、提取css到文件中
确保更新webpack到版本4.2.0。不然mini-css-extract-plugin行不通!
extract-text-webpack-plugin不兼容webpack 4。使用mini-css-extract-plugin代替。
npm i mini-css-extract-plugin css-loader --save-dev
webpack.config.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
}
]
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
};
下面再补充一下webpack4之前是如何引用css文件的
- 可以在src/index.js里引入css文件,到时候直接打包到生产目录下
首先安装插件
npm i style-loader css-loader -D
// 引入less文件的话,也需要安装对应的loader
npm i less less-loader -D
// index.js
import './css/style.css'; // 引入css
import './less/style.less'; // 引入less
console.log('这里是打包文件入口-index.js');
// webpack.config.js
module.exports = {
entry: {
index: './src/index.js'
},
output: {
filename: 'bundle.js',
path: path.resolve('dist')
},
module: {
rules: [
{
test: /\.css$/, // 解析css
use: ['style-loader', 'css-loader'] // 从右向左解析
/*
也可以这样写,这种方式方便写配置参数
use: [
{loader: 'style-loader'},
{loader: 'css-loader'}
]
*/
}
]
}
}
此时打包后的css文件是以行内样式style的标签写进打包后的html页面中,如果样式很多的话,我们更希望直接用link的方式引入进去,这时候需要把
css拆分出来
- 拆分css
npm i extract-text-webpack-plugin -D
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 拆分css样式的插件
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filaneme: 'bundle.js',
path: path.resolve('dist')
},
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextWebpackPlugin.extract({
// 将css用link的方式引入就不再需要style-loader了
use: 'css-loader'
})
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
// 拆分后会把css文件放到dist目录下的css/style.css
new ExtractTextWebpackPlugin('css/style.css')
]
}
此时拆分完css后,打包的html页面就以link的方式去引入css了
9、开发服务器(dev server)
webpack-dev-server提供实时刷新浏览器页面的功能
npm i webpack-dev-server -D
调整package.json
"scripts": {
"start": "webpack-dev-server --mode development --open",
"build": "webpack --mode production"
}
webpack开发服务器非常适合开发(它能使React Dev工具在浏览器中正常工作)
在npm run start时遇到下列错误
解决方法:npm install webpack -D 之后重新运行 npm run start