文章目录
webpack 学习笔记
面试题
webpack内容比较杂乱,先整理面试题,在学习的时候可以抓住重点。
- Webpack的打包过程?
- Webpack的 vendor 和model 有什么区别吗?
- Webpack 的 loader的作用?
- Webpack loader 和 plugin 的区别
- Webpack 做过哪些优化手段?有哪些优化手段?
- Webpack 插件的执行顺序(加载机制)?
- Webpack中怎么实现组件异步加载?
- Webpack如何配置压缩代码?压缩了什么?
- 使用tree-shaking需要注意什么?
概述
Webpack是前端资源构建工具(大工具包含小工具),静态模板打包器。
以入口文件构建依赖关系图 --> 引入依赖形成chunk代码块 --> 根据不同资源进行编译,这个过程叫打包 --> 打包完成后输出bundle文件
说明
1.webpack本身能处理js/json资源,不能处理css/img等其他资源
2.生产环境比开发环境多一个压缩js代码
3.在Webpack中,一切皆模块。Webpack在进行打包的时候,会把所有引入的资源文件都当作模块来处理
Webpack的五个概念
- Entry 指示Webpack以哪个文件为入口起点开始打包,分析构建内部依赖图。
- Output:输出指示Webpack打包后的资源bundles输出到哪里去,以及如何命名。
- Loader:Loader让Webpack能够去处理非JavaScript文件,相当于翻译官(Webpack自身只理解JavaScript/json)
- Plugins:插件可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量等。
- Mode:模式指示Webpack使用相应模式的配置
- development开发环境:能让代码本地调式运行的环境
- production生产环境:能让代码优化上线运行的环境
Webpcak开发模式基本配置
webpack.config.js
webpack的配置文件
所有构建工具都是基于nodejs平台运行的,所以模块化默认采用commonjs
//引入nodejs模块resolve,用来拼接绝对路径
const {resolve} =require('path');
module.exports ={
//入口起点
entry:'./src/index.js',
//输出对象
output:{
filename:'built.js',//输出文件名
//__dirname nodejs变量,代表当前文件的目录绝对路径
path: resolve(__dirname,'build')//输出路径
},
//loader的配置
module:{
rules:[
//详细的loader配置
]
},
//plugins的配置
plugins:[
],
//模式
mode:'development'
}
预处理器Loader
loader:1.下载 2.使用
plugins:1.下载 2.引入 3.使用
打包样式资源
使用的loader
- css-loader:将css文件变成commonjs模块加载js中,模块内容是样式字符串
- style-loader: 创建style标签,将js中的样式资源插入标签内,并将标签添加到head中生效
打包后的css不是单独的文件,是js中的模块
# -D 开发依赖, --save-dev的简写
npm i css-loader style-loader -D
use数组的执行顺序:从右到左
处理css文件
module:{
rules:[//不同文件配置不同loader处理
{
test:/\.css$/, //匹配以css结尾的文件
//使用哪些loader进行处理
use:[
'style-loader',
'css-loader'
]
}
]
}
处理less文件
- less-loader:将less文件编译成css文件
# -D 开发依赖, --save-dev的简写
npm i less-loader less -D
module:{
rules:[//不同文件配置不同loader处理
{
test:/\.less$/, //匹配以css结尾的文件
//使用哪些loader进行处理
use:[
'style-loader',
'css-loader',
'less-loader'
]
}
]
}
打包图片资源 webpack5有改动
webpack4使用url-loader
npm i url-loader file-loader html-loader -D
当依赖的loader只有一个时,可以直接使用loader:‘字符串’
问题:处理不了html中的img图片
解决办法:使用html-loader
问题:因为url-loader默认使用es模块化解析,而html-loader引入图片是commonjs
解决办法:关闭url-loader的es模块化,使用commonjs解析,在url-loader配置中添加esModule:false
rules:[
{//问题:默认处理不了html中的img图片
test:/\.(jpg|png|gif)$/,
loader: "url-loader",
options: {
//图片大小小于8kb,就会被base64处理
//优点:减少请求数量(减轻服务器压力)
//缺点:图片体积会更大(文件请求速度更慢)
limit:8*1024,
//解决:关闭url-loader的es模块化,使用commonjs解析
esModule:false,
//打包之后文件名的hash值取10位,保持原来的后缀名
name:"[hash:10].[ext]",
//设置图片的输出路径
outputPath:"imgs"
}
},
,
{ //处理html文件的img图片(负责引入img,从而能被url-loader进行处理)
test:/\.html$/,
loader:"html-loader"
}
]
打包其他资源 iconfont等 webpcak5有改动
怎么输入,怎么输出
//打包其他资源(除了html/js/css资源以外的资源)
//字体不建议这种写法,因为需要排除的东西过多
{
//排除css、js、html以外的资源
exclude:/\.(css|js|html|less|jpg|png|gif)$/,
loader:"file-loader"
options:{
name:"[hash:10].[ext]"
}
开发服务器 devServer
开发服务器 devServer用来实现自动化,比如自动编译打包,自动打开浏览器,自动刷新浏览器。
只会在内存中编译打包,不会有任何输出文件,比如删除build后,使用devServer不会输出新的build文件。相当于打包后放在本地服务器上运行。
启动devServer指令为:npx webpack-dev-server
(需要安装对应的包)
module.exports={
//.....
//启动devServer指令为:npx webpack-dev-server(需要安装对应的包)
//localhost:3000本地服务器查看
devServer:{
//构建后的路径
contentBase:resolve(__dirname,"build"),
//启动gzip压缩,使代码体积更小,运行更快。
compress:true,
//指定开发服务器的端口号
port:3000,
//自动打开默认浏览器
open:true
}
}
插件plugins
loader:1.下载 2.使用
plugins:1.下载 2.引入 3.使用
打包HTML资源
- html-webpack-plugin 处理html资源,默认会创建一个空的HTML,自动引入打包输出的所有资源(js/css)
# 1.下载插件
npm i html-webpack-plugin -D
//2.引用处理html的插件
const HtmlWebpackPlugin =require("html-webpack-plugin");
module.exports = {
plugins: [
// new HtmlWebpackPlugin()
//需求:需要有结构的HTML文件
//3.使用插件
new HtmlWebpackPlugin({
//将src下的"index.html"作为模板,并自动引入打包输出的所有资源(js/css),输出到build/index.html中
template:"./src/index.html"
})
]
}
开发模式基本配置
/*
开发环境配置,能让代码运行起来
*/
/*
webpack.config.js webpack的配置文件
作用:当运行webpack指令时,会加载里面的配置,打包结果会输出出去
所有的构建工具都基于nodejs平台运行的,模块化默认采用commonjs
*/
/*
loader:1.下载 2.配置(使用)
plugins:1.下载 2.引入 3.使用
*/
//resolve用来拼接绝对路径的方法
const {resolve} = require("path")
//引用处理html的插件
const HtmlWebpackPlugin =require("html-webpack-plugin");
module.exports = {
//webpack配置
//入口起点
entry: {
filename:static/js/[name].js,
path:path.resolve(__dirname.'dist')
},
//输出是对象
output:{
//输出文件名
filename: "js/built.js",
//输出路径
//__dirname是nodejs的变量,代表当前文件的文件夹绝对路径
path:resolve(__dirname,"build")
},
//loader配置
module:{
rules:[
//详细loader配置
//不同文件配置不同loader处理
{
//匹配哪些文件,以.css结尾的文件
test:/\.css$/,
//使用哪些loader进行处理
use:[
//use数组中loader执行顺序:从后往前
//创建style标签,将js中的样式资源插入进行,添加到head中生效
"style-loader",
//将css文件变成commonjs模块加载js中,里面内容是样式字符串,所以css文件不会单独输出
"css-loader"
]
},
{
test:/\.less$/,
use:["style-loader",
"css.loader",
//将less文件编译成css文件
//需要下载less-loader和less
'less-loader'
]
},
//打包其他资源(除了html/js/css资源以外的资源)
//字体不建议这种写法,因为需要排除的东西过多
{
//排除css、js、html以外的资源
exclude:/\.(css|js|html|less|jpg|png|gif)$/,
loader:"file-loader"
options:{
name:"[hash:10].[ext]"
}
}
//处理图片资源
{
//问题:处理html中的img图片
test:/\.(jpg|png|gif)$/,
//使用一个loader时,可直接用loader引用,不用use,
loader: "url-loader",
options: {
//图片大小小于8kb,就会被base64处理
//优点:减少请求数量(减轻服务器压力)
//缺点:图片体积会更大(文件请求速度更慢)
limit:8*1024,
//问题:因为url-loader默认使用es模块化解析,而html-loader引入图片是commonjs
//解析时会出现问题:[object Module]
//解决:关闭url-loader的es模块化,使用commonjs解析
esModule:false,
//打包之后文件名的hash值取10位,保持原来的后缀名
name:"[hash:10].[ext]",
//设置图片的输出路径
outputPath:"imgs" // 路径为:dist/imgs
}
},
{ //处理html文件的img图片(负责引入img,从而能被url-loader进行处理)
test:/\.html$/,
loader:"html-loader"
}
]
},
//plugins的配置
plugins: [
//html-webpack-plugin 处理html资源
//功能:默认会创建一个空的HTML,自动引入打包输出的所有资源(js/css)
// new HtmlWebpackPlugin()
//需求:需要有结构的HTML文件
new HtmlWebpackPlugin({
//复制"index.html",并自动引入打包输出的所有资源(js/css)
template:"index.html"
path:"index.html"
})
//详细pulgins的配置
],
//模式
mode:'development'
// mode:"production"
//启动devServer指令为:npx webpack-dev-server(需要安装对应的包)
//localhost:3000本地服务器查看
devServer:{
//构建后的路径
contentBase:resolve(__dirname,"build"),
//启动gzip压缩,使代码体积更小,运行更快。
compress:true,
//指定开发服务器的端口号
port:3000,
//自动打开默认浏览器
open:true
}
}
Webpcak生产模式基本配置
提取css成单独的文件
打包过后的css在js文件里,通过mini-css-extract-plugin
插件可以把css单独抽出来
1.安装
npm i mini-css-extract-plugin -D
2.引入和使用
//引入
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
//loader配置
module:{
rules:[
{
test:/\.css$/,
use:[
//创建style标签,将js中的样式资源插入进行,添加到head中生效
//"style-loader",
//作用:提取js中的css成单独文件
MiniCssExtractPlugin.loader //取代style-loader,提取js中的css成单独的文件
"css-loader"//将css文整合到js文件中
]
},
]}
plugins:[
//使用
//new MiniCssExtractPlugin()
new MiniCssExtractPlugin({
//输出的css文件重新命名 输出的目录/css/built.css
filename:'css/built.css'
})
]
css兼容性处理 postcss
postcss要在webpack中使用 postcss-loader
、postcss-preset-env
1.安装
npm i postcss-loader postcss-preset-env -D
2.使用
//设置nodejs环境变量
process.env.NODE_ENV="development"
//使用
module:{
rules:[
{
test:/\.css$/,
use:[
MiniCssExtractPlugin.loader
//1.使用loader的默认配置的写法
"css-loader"
//2.修改loader的配置写法
{
loader:"postcsss-loader"
options:{
ident:"postcsss"
plugins:()=>[
//返回一个数组 postcss的插件
//此插件帮助postcss找到package.json中browserslist里面的配置,通过配置加载指定的css兼容性样式,默认找的是browerslist里面的生产环境,如果要找开发环境的,就需要在webpack.config.js中设置node.js坏境变量
require("postcss-preset-env")()
]
}
}
]
},
]}
package.json
文件
"browserslist":{
//开发环境,process.env.NODE_ENV="development"
"development":[
//兼容最近的chrome版本
"last 1 chrome version"
]
//生产环境:默认是看生产环境
"production":[
">0.2%",//兼容98%的浏览器
"not dead",//已经死了的浏览器
"not op_mini all"
]
}
css压缩插件 webpack5有改动
css压缩插件:optimize-css-assets-webpack-plugin
webpcak4的插件
1.安装插件
npm i optimize-css-assets-webpack-plugin -D
2.引用和使用
//1.引用
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin")
//1.使用
plugins:[{
//压缩css,默认配置已经可以解决问题了。
new OptimizeCssAssetsWebpackPlugin()
}]
JS语法检查
语法检查:eslint-loader eslint
注意:只检查自己写的js源代码,第三方的库是不用检查的
设置检查规则:在package.json中eslintConfig中设置
推荐使用airbnb规则需要依赖的库: eslint eslint-plugin-import eslint-config-airbnb-base
1.安装
npm i eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import -D
2.使用
//新版在根目录创建.eslintrc
//老版本
{
test:/\.js$/,
loader:"eslint-loader",
//一定要排除
exclude:/node_modules/,
options:{
//自动修复eslint错误
fix:true
}
}
package.json文件中设置检查规则
"eslintConfig":{
"extends":"airbnb-base"
}
JS兼容性处理
兼容性处理ES6:babel-loader @babel/preset-env @babel/core
基本的js兼容性处理 –> @babel/preset-env 问题:只能转换基本语法,promise不能
1.安装
npm i @babel-loader @babel/preset-env @babel/core -D
2.使用
{
test:/\.js$/,
//一定要排除
exclude:/node_modules/,
loader:"babel-loader",
options:{
//预设:指示babel做什么样的兼容性处理
presets:["@babel/preset-env"]
}
}
全部js兼容性处理 –> @babel/polyfill 被弃用,只需要解决使用了的兼容性问题,但是这个库会将所有兼容性代码引入,体积还会变大。
按需加载,有哪些代码需要做兼容性就引入对应的兼容性代码 –> corejs
1.安装
npm i core-js -D
2.使用
options:{
//配置
presets:[
["@babel/preset-env", //预设包:包含多个常用插件的包
{
//按需加载
useBuiltIns:"usage",
//指定core-js版本
corejs:{
version:3
},
//指定兼容性做到哪个版本浏览器
targets:{
chrome: "60",
firefox:"60",
ie:"9"
}
}
]]
js压缩与html压缩
生产坏境下自动压缩js
//生产坏境下自动压缩js
mode:"production",
plugins:[
new HtmlWebpackPlugin({
//复制"./src/index.html",并自动引入打包输出的所有资源(js/css)
template:"./src/index.html"
//压缩html代码
minify:{
//移除空格
collapseWhitespace:true,
//移除注释
removeComments:true
}
})
]
开发模式基本配置
正常来讲,一个文件只能被一个loader处理,当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序:先执行eslint,在执行babel。
const {resolve} = require("path")
//用于将css从js中抽离成单独文件
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
//css兼容
const OptimizeCssAssetsWebpackPlugin= requir("optimize-css-assets-webpack-plugin")
const HtmlWebpackPlugin= require("html-webpack-plugin")
//css兼容
const commonCssLoader = [
{
loader:MiniCssExtractPlugin.loader,
options:{
publicPath: '../'
}
},
"css-loader",
{ //兼容性,还需要在package.json中定义browserslist
loader: "post-loader",
options: {
ident:"postcss",
plugins:()=>[
require("postcss-preset-env")()
]
}
}
]
module.exports={
entry:"./src/js/index.js",
output: {
filename: "js/built.js",
path: resolve(__dirname,"build")
},
module: {
rules: [
{
test:/\.css$/,
use:[...commonCssLoader]
},
{
test:/\.less$/,
use:[...commonCssLoader, "less-loader"]
},
//配置eslint
{
//在package.json中eslintCofig中配置-->airbnb
//npm install -D eslint eslint --init可以按需配置eslint
test:/\.js$/,
exclude:/node_modules/,
//设置优先执行。
enforce: "pre",
loader: "eslint-loader",
options: {
fix:true
}
},
//兼容性处理
{
test:/\.js$/,
exclude:/node_modules/,
loader: "babel-loader",
options: {
presets:[
"@babel/preset-env",
{
useBuiltIns:"usage",
corejs:{version:3},
targets:{
chrome:"60",
}
}
]
}
},
{
test:/\.(jpg|png|gif)/,
loader: "url-loader",
options: {
limit:8*1024,
name:"[name].[hash:10].[ext]",
outputPath:"imgs",
esModule:false
}
},
{
test:/\.html$/,
loader: "html-loader"
},
{
exclude:/\.(js|css|less|html|jpg|png|gif)/,
loader: "file-loader",
options: {
outputPath:"media"
}
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename:"css/built.css"
}),
//只需要调用
new OptimizeCssAssetsWebpackPlugin(),
new HtmlWebpackPlugin({
template:"./src/index.html",
minify:{
collapseWitespace:true,
removeComments:true
}
})
],
mode: "production"
}