本质上,Webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 Webpack 处理应用程序时,它会递归地构建一个依赖关系图(Dependency Graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle。
在webpack看来,前端的所有资源文件(js、css、img、json…)都会作为模块处理。然后会根据模块的依赖关系进行静态分析,打包生成对应的静态资源。
在学习之前我们必须先要搞明白webpack的五个基本核心概念:
entry:
口指示webpack以哪个文件为入口起点开始打包,分析构建内部的依赖图。
output:
输出指示 webpack打包后的资源bundles输出到哪里去,以及如何命名
Loader:
让webpack去处理非JavaScript资源的文件,比如css、img等,将他们可以处理成一个webpack可以识别的资源,可以理解成一个翻译的过程。(webpack自身只能理解json和js)
plugins:
插件可以用来执行更加广的任务,插件的范围包括打包优化和压缩
mode:
模式指示webpack使用相应模式的配置。
开发模式(development):配置比较简单,能让代码本地调试运行的环境。
生产模式(production):代码需要不断优化达到性能最好。能让代码优化上线运行的环境。
都会自动启用一些插件,生产模式使用插件更多
首先需要确定有node环境
接着全局下载webpack
npm i webpack webpack-cli -g
注意:在项目中安装还需要本地安装
首先创建src、build目录,在src创建js文件,并写入es6的代码。
然后使用分别使用以下命令编译查看结果:
webpack ./src/index.js -o ./build/ --mode=development //开发环境下
webpack ./src/index.js -o ./build/ --mode=production //生产环境下
并且常识打包css文件,结果发现会报错,因此我们可以得出以下三个结论:
这时webpack的配置文件,一般与src文件同级
作用是只是webpack干什么干什么,怎样干,一般在执行webpack命令时,会加载里面的配置。
因为前面说到构建工具是基于node环境的,因此我们这里的模块化采取common.js
下面是一个webpack.config.js的模板:
const path= require('path');
module.exports={
// 入口起点
entry:'./src/index.js',
// 输出
output:{
// 输出文件名
filename:'built.js',
path:path.resolve(__dirname,'build')
},
// loder配置
module:{
rules:[
// 详细的loder配置
]
},
// plugins配置
pligins:{
// 详细的pligins配置
},
// 开发模式
mode:'development'
}
由上文知道我们打包除js/json以外文件需要添加loader操作
因此我们在处理样式文件时需要下载必须的两个插件: 'style-loader', 'css-loader'
因为less与sass文件最终都是要转为css文件的,如果打包这些文件在下载相应的loader即可。
// loder配置
module: {
rules: [
// 详细的loder配置
// css打包处理
{
// 匹配哪些文件
test: /\.css$/,
// 使用哪些loader进行处理
use: [
'style-loader',
'css-loader'
]
},
// less打包处理
{
test:/\.less$/,
use:[
'style-loader',
'css-loader',
'less-loader'
]
}
]
},
注意:
打包hmtl资源需要使用plugins插件来进行。
插件的使用流程与loader不同,顺序是下载、导入、使用。而loader是下载、使用
首先我们下载html-webpack-plugin插件。
然后导入:
const Htmlwebpackplugin = require('html-webpack-plugin');
接在在plugins数组中操作即可:
plugins:[
new Htmlwebpackplugin({
//复制其资源到build,并自动引入打包输出所有资源
template:'./src/index.html'
})
],
此插件的功能是默认在build文件夹中创建一个html文件,自动引入相应的css、js资源文件
打包图片资源需要添加loader:url-loader,file-loader(url-loader的依赖包)
也可以设置option内容,优化图片格式,在范围内的图片压缩为base64格式减少服务器请求次数。
{
test:/\.(jpg|png|gif)$/,
loader:'url-loader',
options:{
limit:120*1024
}
},
{
test:/\.html$/,
loader:'html-loader'
}
html-loader是用来处理html文件的img图片(负责引入img,从而可以内url-loader进行处理)
其他资源一般是指除js、css等常规资源等以外的资源。比如iconfont等。我们这里使用iconfont来举例说明
我们只需要引入url-loader在进行配置即可
// 打包其他资源
{
exclude:/\.(css|html|js)$/,
loader:'url-loader'
}
webpack为我们提供了用于实时刷新自动编译的服务器。这个服务器的特点是不会有输出,只会在内存中编译打包,服务关闭,内存中的相应数据也会销毁。
这里的用法是先本地下载webpack-dev-server包
然后再webpack.config.js 中进行配置。
devServer:{
// 项目构建后的路径
contentBase:path.resolve(__dirname,'build'),
// 启动gzip压缩
compress:true,
// 设置端口号
port:3000,
// 启动后是否自动打开浏览器
open:true
}
注意:webpack5.X以上版本启动服务器需要使用命令
npx webpack serve
其实开发环境的配置就是将我们前面所讲的打包各种资源全部结合起来。
需要注意的是开发环境配置是可以让代码运行的。
运行代码的指令:
webpack:打包输出到目标文件
npx webpack serve:只会在内存中编译打包
下面我们直接上配置文件的代码:
const path = require('path');
const Htmlwebpackplugin = require('html-webpack-plugin');
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: path.resolve(__dirname, 'build')
},
module: {
rules: [
// 打包css
{
test:/\.css$/,
use:[
'style-loader',
'css-loader',
]
},
// less打包处理
{
test:/\.less$/,
use:[
'style-loader',
'css-loader',
'less-loader'
]
},
//打包图片资源
{
test:/\.(jpg|png|gif)$/,
loader:'url-loader',
options:{
limit:120*1024,
name:'[name].[ext]',
outputPath:'image'
}
},
{
test:/\.html$/,
loader:'html-loader',
},
// 打包其他资源
{
exclude:/\.(css|html|js)$/,
loader:'url-loader',
options:{
name:'[name].[ext]',
outputPath:'media'
}
}
]
},
plugins: [
new Htmlwebpackplugin({
template:'./src/index.html'
})
],
mode: 'development',
// devserver
devServer:{
// 项目构建后的路径
contentBase:path.resolve(__dirname,'build'),
// 启动gzip压缩
compress:true,
// 设置端口号
port:3000,
// 启动后是否自动打开浏览器
open:true
}
}
生产环境是项目上线时需要采用的,为了让我们的代码更快更平稳。下面让我们一点点的学习生产环境的基本配置。
我们再开发环境下时,处理css样式文件是通过标签字符串的方式进行引入的,这样无疑增加了js标签渲染的压力,也可能会出现闪屏的可能。因此我们要想办法将css提取成单独的文件。
首先我们先捋一下思路。原本处理css文件的两个步骤时先使用css-loader帮我们分析出各个css文件之间的关系,把各个css文件合并成一段css;再使用style-loader将其挂载再我们的style上
因此我们这里第一步不变,第二步引入插件mini-css-extract-plugin
生成单独的css文件。思路清晰后我们直接写代码
引入插件:
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
使用插件自带的loader:
{
test:/\.css$/,
use:[
// 'style-loader',
// 替换为抽离css的loaderr
MiniCssExtractPlugin.loader,
'css-loader'
]
}
使用插件(设置文件输出位置):
plugins:[
new MiniCssExtractPlugin({
filename:'css/build.css'
})
],
首先我们需要安装两个loader:postcss-loader和postcss-preset-evn。
npm i postcss-loader postcss-preset-env -D
再package.json中添加如下配置:
"browserslist":{
"development":[
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
"production":[
">0.2%",
"not dead",
"not op_mini all"
]
}
再webpack.config.js文件:
const path = require('path');
const Htmlwebpackplugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// 设置nodejs的环境变量
// process.env.NODE_ENV = 'development'
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: path.resolve(__dirname, 'build')
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
// 修改postcss-loader的默认配置
/*
帮postcss找到package.json中的broswerslist里面的配置,通过配置加载指定的css兼容性
*/
{
loader: 'postcss-loader',
options: {
postcssOptions:{
ident: 'postcss',
plugins: [
require('postcss-preset-env')()
]
}
}
}
]
}
]
},
plugins: [
new Htmlwebpackplugin({
template: './src/index.html'
}),
new MiniCssExtractPlugin({
filename: 'css/build.css'
})
],
mode: 'development'
}
需要注意的是要想再开发环境下进行打包处理需要使用如下代码来配置nodejs的环境变量:
process.env.NODE_ENV = 'development'
需要引入插件optimize-css-assets-webpack-plugins(这里使用cnpm引入插件。npm无法引入)
最后直接引入插件实例化即可。
cnpm i optimize-css-assets-webpack-plugin -D
使用方法:
const Optimizecssassetswebpackplugin = require('optimize-css-assets-webpack-plugin');
plugins: [
new Optimizecssassetswebpackplugin()
],
首先应该下载eslint-loader和eslint对我们js进行检查。
其次就是添加检查规则,我们这里使用GitHub上有名的语法规则指南airbnb。
需要下载三个插件eslint-config-airbnb-base、eslint-plugin-import和eslint
cnpm i eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import -D
接配置loader:
module: {
rules: [
{
test:/\.js$/,
exclude:'/node_modules/',
loader:'eslint-loader',
options:{
// 自动修复错误
fix:true
}
}
]
}
最后再package.json中给eslint配置继承airbnb语法
"eslintConfig": {
"extends": "airbnb-base"
}
即可。
当我们再处理js代码时,使用es6语法时,webpack时不会将es6进行编译的,这就导致了ie等旧版浏览器无法识别es6的代码,因此我们需要再编译的时候直接将es6代码进行编译成es5的代码。
首先我们需要两个三个基础包:
babel-loader
@babel/preset-env
@babel/core
其实这三个包下载好以后我们配置一个babel-loader就可以完成对简单es6语法的编译。但是对于稍微复杂的语法,比如promise等就无法完成编译。一次我们还要引入以下包:
此外我们还需要兼容一些复杂的es6功能,就有需要我们下载一个包:
core-js。
注意:这里引入建议都是使用cnpm引入
配置webpack.config,js文件:
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
// 按需加载
useBuiltIns:'usage',
corejs:{
version:3
},
// 指定兼容性浏览器
targets:{
chrome:'70',
firefox:'60',
ie:'9',
safari:'10',
edge:'17'
}
}
]
]
}
}
]
}
完成以后我们就可以将es6的语法自动编译成我们浏览器可以识别的语法啦!
前面说到webpack自身是理解js和json的。因此我们在压缩js代码时只需要将mode改为生产环境下即可。
在webpack5以前我们压缩js代码还要需要在html-webpack-plugin插件中设置一些配置,但是在webpack5以后这些都不需要配置,因为在生产环境下webpack都会为我们处理好。
因此只需要更改wenpack.config.js中的mode值即可:
mode: 'production'
源码:
const path = require('path');
const Htmlwebpackplugin = require('html-webpack-plugin');
const Minicssextractplugin = require('mini-css-extract-plugin');
const Optimizecssassetswebpackplugin = require('optimize-css-assets-webpack-plugin');
// 是否在开发环境下执行
// css/less文件处理浏览器兼容的复用抽离:
module.exports = {
entry: "./src/js/index.js",
output: {
filename: 'js/built.js',
path: path.resolve(__dirname, 'build')
},
module: {
rules: [
// 提取css成单独文件+css兼容性处理(适配浏览器)
{
test: /\.css$/,
use:
[
Minicssextractplugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
ident: 'postcss',
plugins: [
require('postcss-preset-env')()
]
}
}
}
]
},
// 处理less成单独文件
{
test: /\.less$/,
use: [
Minicssextractplugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
ident: 'postcss',
plugins: [
require('postcss-preset-env')()
]
}
}
},
'less-loader'
]
},
//eslint语法检查
{
test: /\.js$/,
// 优先执行
exclude:/node_modules/,
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true
}
},
//js兼容性处理
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
// 按需加载
useBuiltIns: 'usage',
corejs: {
version: 3
},
// 指定兼容性浏览器
targets: {
chrome: '70',
firefox: '60',
ie: '9',
safari: '10',
edge: '17'
}
}
]
]
}
},
//图片加载
{
test: /\.(jpg|png|gif)$/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
outputPath: 'image',
esModule: false
}
},
// 处理html中的图片
{
test: /\.html$/,
loader: 'html-loader'
},
// 处理其他资源
{
exclude: /\.(less|css|html|js|jpg|png|gif)$/,
loader: 'url-loader',
options: {
outputPath: 'media'
}
}
]
},
plugins: [
new Htmlwebpackplugin({
template: './src/index.html'
}),
new Minicssextractplugin( {
filename: 'css/build.css'
}),
// 压缩css样式
new Optimizecssassetswebpackplugin()
],
mode: 'production'
}
package.json配置:
"devDependencies": {
"@babel/core": "^7.13.10",
"@babel/preset-env": "^7.13.12",
"babel-loader": "^8.2.2",
"core-js": "^3.9.1",
"css-loader": "^5.1.4",
"eslint": "^7.22.0",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-loader": "^4.0.2",
"eslint-plugin-import": "^2.22.1",
"file-loader": "^6.2.0",
"html-loader": "^2.1.2",
"html-webpack-plugin": "^5.3.1",
"less-loader": "^8.0.0",
"mini-css-extract-plugin": "^1.3.9",
"optimize-css-assets-webpack-plugin": "^5.0.4",
"postcss-loader": "^5.2.0",
"postcss-preset-env": "^6.7.0",
"style-loader": "^2.0.0",
"url-loader": "^4.1.1",
"webpack": "^5.27.2",
"webpack-cli": "^4.5.0",
"webpack-dev-server": "^3.11.2"
},
"browserslist": {
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
"production": [
">0.2%",
"not dead",
"not op_mini all"
]
},
"eslintConfig": {
"extends": "airbnb-base"
}
webpack优化分为开发环境优化和生产环境优化
开发环境优化:优化打包速度,优化代码调试
生产环境优化:优化打包速度,优化代码运行的性能
后续更新,提上日程。。