webpack是什么
webpack是一个非常实用的静态模块打包工具,它通过递归的方式构建一个包含应用程序需要的所有模块的依赖图,然后将这些文件打包成一个或多个bundle输出
为什么要使用webpack
早期的开发中都是将各种静态文件(比如图片,CSS等)手动引入到html中,然后直接在浏览器中运行html文件;在这个时期,遇到大型项目时要么将所有的JS全部写在一个文件中,要么是引入多个脚本;前一种方式会导致代码混乱;后一种方式会导致HTTP请求过多;
随着前端技术的发展,开始使用模块化对代码进行分割,让代码能够复用且更方便维护,但浏览器对模块化的支持并不统一;
webpack最核心的功能就是解决模块之间的依赖问题,通过对webpack的简单配置即可完成代码转换,压缩,文件优化,模块加载及打包等功能
安装webpack
npm install webpack webpack-cli -D
核心概念
entry: 构建入口
entry用于告诉webpack应该使用哪个模块做为构建的开始;其默认值为./src/index.js
module.exports = {
entry: './src/main.js'
}
output: 构建输出
output指定了webpack构建完成后的文件输出位置以及输出后的文件名等信息;
const path = require('path') // nodeJs内置的path模块
module.exports = {
entry: './src/main.js',
output: {
filename: 'main.[hash].js', // 输出文件的文件名
path: path.resolve(__dirname, 'dist')
// path属性用于指定输出的文件路径,它必须接收绝对路径
// path.resolve()方法用于将相对路径转换成绝对路径
}
}
[hash]
: [hash]用于解决静态文件缓存问题;静态文件内容更改而文件名不更改的情况下,可能会因为浏览器缓存问题而获取不到新的内容,通过hash可以让每一次打包的文件名不重复
mode: 配置模式
webpack会根据配置模式自动调用相应的内置优化项; 可选的配置模式有development
, production
, none
, 默认值为production
配置模式可以在webpack的配置文件中显式的指定
module.exports = {
mode: 'development'
}
在实际的项目开发中,更多的是通过脚本的方式执行CLI,通过CLI的参数传递
<!-- package.json -->
"scripts": {
"build": "webpack --mode=production",
"dev": "webpack-dev-server --mode=development"
}
loader: 模块代码转换器
loader用于对模块中的源代码进行转换,webpack本质上只能理解JavaScript和JSON文件,如果要解析其他代码就需要对代码进行转换,比如将typeScript代码转换成javascript代码;
常用的loader属性
test
: 使用正则筛选出需要使用loader的文件use
: 转换时需要使用的loader,可以同时使用多个loader;通过对象的方式可以对loader进行个性化的配置include
: 指定loader必须要应用的文件夹exclude
: 指定loader需要排除不处理的文件夹
loader的执行顺序
loader的执行顺序是从下往上,从右往左;也就是说,在代码中越靠后的loader越先执行;在下面的例子中,css-loader比style-loader先执行
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', ''css-loader]
}
]
}
}
plugin
webpack的插件系统,通过插件可以扩展webpack的功能
基础配置
webpack解析时默认从webpack.config.js
文件提取配置,所以将webpack的相关配置都写到这个文件中
<!-- webpack.config.js -->
const path = require('path')
module.exports = {
entry: './main.js',
output: {
filename: 'index.js',
path: path.resolve(_dirname, 'dist')
}
}
以上就是一个最基础的webpack配置,以当前(webpack.config.js
所在的目录)目录下的main.js
为入口开始构建,输出到当前目录下的dist文件夹中;
配置HTML模板
在单页面应用开发中都需要使用一个html文件作为模板;html-webpack-plugin用于指定一个html文件作为模板,并以这个模板为基础引入打包后的js,css等文件,然后根据output的配置输出
安装
npm install html-webpack-plugin -D
配置
<!-- webpack.config.js -->
let HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
// 省略其他代码s
plugins: [
new HtmlWebpackPlugin({
template: './index.html', // 指定模板文件路径
filename: 'index.html', // 指定打包后输出的模板文件名
minify: { // 指定模板压缩的规则
removeAttributeQuotes: true, // 删除属性的双引号
collapseWhitespace: true, // 折叠空行
},
hash: true // 添加hash戳,hash可以避免缓存问题
})
]
}
在上面的配置中,指定了模板的路径(template
)以及打包完成后输出的文件名称(filename
), 同时指定了模板文件的压缩规则(minify
), 为解决缓存问题添加了hash
戳,输出的模板文件都会带上hash
值;更多html-webpack-plugin的配置可以参考官方文档
本地开发服务配置
webpack-dev-server提供了一个本地的web开发服务和热更新的能力;通过这个本地server直接访问应用可以更好的开发和调试
安装
npm install webpack-dev-server -D
配置
module.exports = {
devServer: {
port: '8080', // 开发服务端口
host: 'localhost',
progress: true, // 配置打包进度条
contentBase: './dist', // 指定静态服务的启动文件夹
}
}
在package.json
文件中配置一个脚本,
<!-- package.json -->
"scripts": {
"dev": "webpack-dev-server --mode=development"
}
此时通过npm run dev
就可以启动一个本地开发服务了;更多关于webpack-dev-server的配置可以参考官方文档
webpack中css的配置
普通css的配置
webpack中css的解析主要依赖两个loader来完成:css-loader,style-loader
css-loader
主要负责解析@import和url()
style-loader
的主要作用是将css通过style标签的方式添加到模板文件中
安装
npm install style-loader css-loader -D
配置
<!-- webpack.config.js -->
module.exports = {
// 省略其他代码
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
}
因为需要先解析css中的@import和url()语法,所以css-loader应该写style-loader之后
less和sass的配置
less和sass的解析依赖于less-loader和 sass-loader;
使用这两个loader之前需要安装less和sass模块
安装
npm install less less-loader node-sass sass-loader -D
配置
<!-- webpack.config.js -->
module.exports = {
// 省略其他代码
module: {
rules: [
{
test: /\.less/,
use: ['style-loader', 'css-loader', 'less-loader']
},
{
test: /\.scss/,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {}
}
]
}
]
}
}
个性化loader配置
: 在上面的配置中,scss-loader使用了对象语法进行配置,这种方式可以通过options对象来对loader进行更多个性化的配置
添加浏览器前缀
由于浏览器对css新属性的兼容性不统一,所以一些新的css属性在使用的时候需要为不同的浏览器加上前缀
autoprefixer通过postcss配置后可以为自动为css添加不同浏览器的前缀
安装
npm install autoprefixer postcss-loader -D
配置
<!-- webpack.config.js -->
module.exports = {
// 省略其他代码
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader','postcss-loader' 'css-loader']
}
]
}
}
接下来还需要通过postCSS配置autoprefixer才能自动添加前缀
<!-- postcss.config.js -->
const autoprefixer = require('autoprefixer')
module.exports = {
plugins: [autoprefixer]
}
提取css到单独文件中
通过前面的配置,已经可以解析css并且将css通过style标签的形式插入到模板中; 但是如果css内容过多,则会让模板文件中的css显得臃肿,这个时候就需要将css单独抽离出一个文件,以link的方式引入模板
mini-css-extract-plugin插件用于将CSS提取到单独的文件中
安装
npm install mini-css-extract-plugin -D
配置
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
// 省略其他代码
plugin: [
new MiniCssExtractPlugin({
filename: 'css/index.css'
})
]
}
filename
: 抽离之后的css文件名称,如果使用路径的方式则会将文件抽离到指定的路径下,以上面的代码为例,index.css
会抽离到./dist/css/index.css
使用mini-css-extract-plugin插件之后,css将会抽离成单独的文件,所以需要使用MiniCssExtractPlugin.loader替换原有的style-loader
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
// 省略其他代码
plugin: [
new MiniCssExtractPlugin({
filename: 'index.css' // 抽离后的css文件名
})
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
}
}
webpack中JS的配置
由于浏览器对新的ES语法支持并不是一致,为了保证代码的兼容性,需要将新的ES语法(ES6,ES7,ES8等)转换为浏览器都支持ES5语法;在webpack中,这个转换的功能主要通过babel来完成
安装
npm install babel-loader @babel/core @babel/preset-env -D
配置
module.exports = {
// 省略其他代码
module: {
rules: [
{
test: '/\.js$/',
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env'
]
}
},
include: path.resolve(__dirname, 'src'), // 希望应用的文件夹
exclude: /node_modules/ // 需要排除的文件夹
}
]
}
}
文件压缩
webpack中的文件压缩通过配置optimization来完成
module.exports = {
// 省略其他代码
optimization: [
]
}
css文件压缩
optimize-css-assets-webpack-plugin插件可以用于css文件的压缩
安装
npm install optimize-css-assets-webpack-plugin -D
配置
const OptimizeCss = require('optimize-css-assets-webpack-plugin')
module.exports = {
// 省略其他代码
optimization: [
new OptimizeCss()
]
}
js文件压缩
uglifyjs-webpack-plugin插件用于JS文件的压缩
安装
npm install uglifyjs-webpack-plugin -D
配置
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
// 省略其他代码
optimization: [
new UglifyJsPlugin({
parallel: true
})
]
}
图片的配置
webpack中的图片配置可以使用url-loader来完成,url-loader与file-loader功能相似;但是它可以在图片大小低于指定的限制时,将图片转换为base64格式,以此减少HTTP请求
安装
npm install url-loader -D
配置
module.exports = {
// 省略其他代码
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10240, // 单位为字节
outputPath: 'img/'
}
}
]
}
]
}
}
outputPath
: 指定图片输出路径,已上面的配置为例,图片文件将输出到./dist/img/
目录下
全局变量的配置(以jquery为例)
当下前端开发的主流框架都是以数据驱动的,很少去操作DOM;但是如果项目业务特殊需要用到jQuery的话,为了避免每一次使用的时候都通过import去引入,可以使用webpack配置一个全局变量
webpack全局变量的配置主要使用webpack的内置模块(内置模块不需要通过npm安装,直接使用即可)ProvidePlugin来完成,详细内容可以参考官方文档
配置
npm install jquery
module.exports = {
// 省略其他代码
plugins: [
new webpack.ProvidePlugin({
$: "jquery"
})
]
}
打包清空输出目录
为了避免多次打包后输出目录混乱(举例:每次打包都输出一个名称带hash的文件,多次打包后就会产生多个文件在同一个目录中,但是只有最后一次输出的文件才有用)的问题,可以通过clean-webpack-plugin插件,在每一次打包的时候都将输出目录清空,这样,每一次打包后的输出文件夹中都会比较干净
安装
npm install clean-webpack-plugin -D
配置
const CleanWebpackPlugin = require('clean-webpack-plugin')
module.exports = {
// 省略其他代码
plugins: [
new CleanWebpackPlugin()
]
}
写在最后
本文主要了解了webpack中的一些核心概念并介绍了一些常用配置所需要的插件,loader等,通过这些配置就已经可以满足多数场景的基本开发需求了
本文所对应的配置源码已提交到我的github
更加个性化的配置可以参考进阶配置
end