概念
webpack是一个模块打包工具,由于前端大量地采用模块化开发,所以模块打包工具应运而生,诸如parcel、webpack等都是时下流行的优秀的打包工具。
模块打包,通俗地说就是:找出模块之间的依赖关系,按照一定的规则把这些模块组织合并为一个JavaScript文件。
Webpack认为一切都是模块,JS文件、CSS文件、jpg/png图片等等都是模块。Webpack会把所有的这些模块都合并为一个JS文件,这是它最本质的工作。当然,我们可能并不想要它把这些合并成一个JS文件,这个时候我们可以通过一些规则或工具来改变它。
入口entry
这个就是设置webpack入口的起点,webpack会根据这个入口来查找到对应的依赖模块
我们可以在webpack.config.js中配置这个入口文件
module.exports = {
entry: './path/to/my/entry/file.js'
};
出口output
这里是用来设置输出文件的文件名或者是输出文件的位置。它会创建一个bundles,默认是./dist,基本上,所有内容都会被输出到这个文件夹中。同样我们可以在webpack.config.js中配置
const path = require('path'); //node.js的模块,用于操作文件路径
module.exports = {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),//设置`dist`文件夹
filename: 'my-first-webpack.bundle.js'//文件名
}
};
loader
webpack是认识javascript的,但是它不认得css跟html或者其他文件,所以我们就通过这个来设置让webpack知道对应的处理方式,并转换成对应的模块
我们需要设置两个东西,一个是test属性,就是让webpack知道要处理啥类型的文件,还一个是use属性,就是让webpack知道用什么loader处理
const path = require('path');
const config = {
output: {
filename: 'my-first-webpack.bundle.js'//输出文件名
},
module: {
rules: [
{ test: /\.txt$/, use: 'raw-loader' }//遇到.txt时用raw-loader处理一下
]
}
};
module.exports = config;
上面在rules上面设置了一个数组,意思是,当webpack在处理时发现.txt的路径,就使用raw-loader来处理一下再打包
模式
我们可以选择开发者模式,或者选择生产模式,两者几乎没有实际区别,但是一般来说,生产模式要比开发者模式压缩一些,而且需要设置浏览器缓存。当然这都取决于我们怎样设置。
module.exports = {
mode: 'production'//生产模式,压缩版
};
module.exports = {
mode: 'development'//开发者模式,会有注释等信息
};
安装
在这里不推荐使用全局安装
mkdir webpack //创建一个目录webpack
cd webpack
yarn init -y
yarn add webpack webpack-cli --dev
上面我们初始化yarn后,使用yarn来add了webpack跟webpack-cli(webpack的命令行工具)
这时候会发现多了node_modules和package.json与yarn.lock三个文件
根据官方文档,我们还需要调整package.json 文件,以便确保我们安装包是私有的(private),并且移除 main 入口。这可以防止意外发布代码。
练习导出js文件
mkdir src && cd src &&touch index.html index.js index.css
我们新建一个目录webpack并在终端内执行上面这段代码就可以创建src目录,并创建html、css、js文件
配置文件
新建webpack.config.js,并且写入代码
const path = require('path');
module.exports = {
mode: 'development',//开发者模式
entry: './src/index.js',//进入src,找到index.js文件
output: {
filename: 'bundle.js', //输出文件名为bundle.js
path: path.resolve(__dirname, 'dist')//输出目录名为dist
}
};
运行
由于我们是在创建的目录内安装了webpack,所以我们需要运行webpack的话就需要运行./node_modules/.bin/webpack
不过有更简单的方法
npx webpack --version 查看版本
npx webpack 运行webpack
浏览器缓存机制
由于浏览器缓存机制的存在,我们的后端可以在httpHeader中设置让浏览器缓存,这样在不修改网页原文件时,用户就可以通过浏览器缓存,当第二次进入网页时,浏览器缓存就会读取缓存中的文件,提高刷新网页的效率。
浏览器缓存机制主要识别文件名,如果我们在部署新版本时不更改资源的文件名,浏览器可能会认为它没有被更新,就会使用它的缓存版本。也就是说,如果我们使用发布的文件名都是bundle.js,当我们设置了浏览器缓存时,即使修改了bundle.js很有可能浏览器会以为我们没有修改过js文件,所以读取的依然是旧版本的文件。
那么只要我们修改了bundle中的文件名,这样浏览器不就知道我们修改过js或者css文件了吗?
这里需要注意,我们不能设置index.html的缓存,因为index.html是入口,浏览器通过这个入口来识别我们是否更新了css或者js文件,如果对首页做了缓存,那么浏览器一直加载缓存中的首页。
现在我们需要一个不同名的机制,那么webpack也可以帮我们做,那就是在output对象中设置。
设置output输出文件的名称
使用入口名称:
filename: "[name].bundle.js"
使用内部 chunk id
filename: "[id].bundle.js"
使用每次构建过程中,唯一的 hash 生成
filename: "[name].[hash].bundle.js"
使用基于每个 chunk 内容的 hash
filename: "[chunkhash].bundle.js"
长期缓存机制下生成hash
filename: '[name].[contenthash].html'
长期缓存机制下生成hash这个一般来说是我们喜欢用的,它会在内部进行hash运算,生成一串hash码,然后跟我们的输出文件名做拼接
清理dist以及优化运行指令
由于我们output的文件名不同,所以我们需要在运行webpack之前删除原先的dist文件,否则会越积累越多。
我们可以在package.json中的script内设置
"scripts": {
"build": "rm -rf dist && npx webpack"
},
它的含义是我以后可以通过yarn build来先删掉dist再执行npx webpack这个cli命令
练习导出html文件
我们需要安装html插件,并且调整webpack.config.js文件
yarn add html-webpack-plugin --dev
上面代码新增了一个html插件plugin
webpack.config.js设置为
const path = require('path');
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist')
},
+ plugins: [
+ new HtmlWebpackPlugin({
+ title: 'Output Management'
+ })
+]
};
这时候运行yarn build后发现dist中会有index.html。
上面的代码中title是什么?打开dist/index.html就知道了,可以通过设置这个来将dist文件中的title做修改。
但是这时候的index.html跟我自己创建的在src内的index.html无关,如果我想用让它按照我给的index.html来生成应该怎么做呢?
我们在new HtmlWebpackPlugin内写入以下代码
new HtmlWebpackPlugin({
template: 'src/index.html'
})
这样就可以使用我们自己写的html来打包了
练习导出css
我们可以使用两种方式来处理css类型。一种是使用css-loader,另外一种就是使用css plugin。
使用css-loader方式
在webpack.config.js文件中设置
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}
]
}
}
然后安装
yarn add style-loader --dev
yarn add css-loader --dev
这时候使用http-server或者使用webpack自带的server来查看生成的html,就会发现css被插入index.html里。
使用plugin插件加载css
使用这种方式跟css-loader方式不同的是,它会在新生成的dist文件夹中生出css文件,并且帮助调整好引用。这样是一种css样式与js文件分离的方法,能够提高加载速度
css-loader是直接加载到js的bundle中,再写入页面里。可以理解是直接写到页面的style中。
下载
yarn add mini-css-extract-plugin --dev
用法:
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [
new MiniCssExtractPlugin({
// 类似于 webpackOptions.output 中的选项
// 所有选项都是可选的
filename: '[name].[contenthash].css',
chunkFilename: '[id].[contenthash].css',
ignoreOrder: false, // 忽略有关顺序冲突的警告
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
// 你可以在这里指定特定的 publicPath
// 默认情况下使用 webpackOptions.output 中的 publicPath
publicPath: '../',
hmr: process.env.NODE_ENV === 'development',
},
},
'css-loader',
],
},
],
},
};
webpack-dev-server
这个是一个开发工具,能够帮我们快速开发,就跟http-server一样,但是它更加强大
安装
yarn add webpack-dev-server --dev
配置
1、首先我们需要将mode修改成 mode: 'development',
2、在pageage.json中写:
"start": "webpack-dev-server --open",
上面这样配置就可以使用yarn start来快速打开
3、在webpack.config.js中写
module.exports = {
+ devtool: 'inline-source-map',//这个设置可以让我们很快知道被打包后的文件哪个位置出错了
+ devServer: {
+ contentBase: './dist',
+ },
}
上面代码是告诉webpack-server将 dist 目录下的文件 serve 到 localhost:8080 下。serve的意思是将资源作为 server 的可访问文件
如果我们更改任何源文件并保存它们,web server 将在编译代码后自动重新加载。而且此时删除了dist文件夹,server依然存在。
根据模式选择不同命令
在生产模式下,我们需要浏览器缓存,所以需要使用yarn build命令来构建dist文件包,但是当我们开发时,我们只需要yarn start来查看页面就可以了,所以我们需要配置两种模式的config.js文件
- 创建
webpack.config.prod.js,放生产模式下的代码 - 默认的
webpack.config.js为开发模式 - 修改
pageage.json文件
开发模式跟生产模式的不同点:
开发模式下我们需要css loader跟webpack server
生产模式下我们需要css plugin,不需要webpack server
所以我们把代码整合一下即可,这里就不贴整合后的代码了,请访问github查看
这里贴一下设置的package.json的配置
"build": "rm -rf dist && npx webpack --config webpack.config.prod.js"
使用--config webpack.config.prod.js来让这个命令行找到对应的config.js文件再进行处理
参考文档
webpack中文:www.webpackjs.com/concepts/
html插件:www.webpackjs.com/plugins/htm…
html插件配置:github.com/jantimon/ht…
css插件:webpack.js.org/plugins/min…
css loader:www.webpackjs.com/loaders/css…
DevServer:webpack.docschina.org/guides/deve…