相关
安装
1.初始化: npm init -y(
默认初始化,不加-y一路回车)
2.安装一下webpack:全局:npm install -g webpack
当前项目: npm install --save-dev webpack
webpack 4以上还需要安装webpack-cli:
npm install --save-dev webpack webpack-cli
3.创建配置文件:webpack.config.js
//六大体系
module.exports={
//一:打包生成环境
//1.开发development 2.生产模式(代码压缩混淆)production
mode:“production”,
//二:入口(js来源)
entry:'目标js', //多个时可以用数组/对象(不能合并jq等插件)
//三:出口(生成的配置)
outpu:{
filename: '生成的文件名.js',
path: '/生成的路径'
},
//四:loader
//(webpack默认只能打包js文件,打包其他入css图片等需要在这里定义(先npm导入对应包))
//如npm install --save-dev css-loader
module:{
//匹配文件规则
rules:[
{
//正则
test:/\.css$/,
//对应包:顺序:从后到前
use:['css-loader']
}
]
},
//五:plugin:插件(一些插件:如打包html的html-webpack-plugin)
//(需要先在前面导入对应插件 )
plugins:[
// 插件
],
//六:开发环境配置:实现自动化
devServer:{
}
}
创建打包脚本命令
- 全局安装webpack下可以直接执行命令:
webpack
- 局部安装情况下可以使用:
npx webpack
1.在package.json中的scripts节点中定义脚本命令
2.npm run 对应定义的脚本命令
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack -p",//上线模式打包
"dev": "webpack"//开发模式打包
},
- 当名字
不为webpack.config.js
时需要自动指定:
npm webpack(可以改为脚本命令) --config 对应文件名
- 当脚本命令只有webpack时-----输入脚本命令时带参数:
npm dev --(双杆后面带参数) -p
创建服务(devServer)
- 热部署
1.npm install --save-dev webpack-dev-server
2.npx webpack-dev-server
3.通过生成的localhost进行访问
devServer:{
//要运行的项目的根目录(根路径)
constentBase:resolve(_dirname,'对应目录'),
//启动gzip压缩
compress:true,
//运行的端口
port:8080,
//自动打开浏览器
open:true,
//服务代理----> 解决跨域
proxy:{
//匹配对应的路径进行代理
//例如匹配到http://localhost/api将代理为https://xxx
'/api':{
target:'https://xxx',
//发送请求是,请求路径重写,将'/api'重写为''
pathRewrite:{
'^/api':''
}
}
}
}
五个核心
//webpack.config.js
module.exports = {
//1.入口
entry: "./runoob1.js",
//2.出口
output: {
path: __dirname,
filename: "bundle.js"
},
//3.其他资源
module: {
rules: [
{ test: /\.css$/, loader: "style-loader!css-loader" }
]
},
//4.插件
plugins:[
new webpack.BannerPlugin('菜鸟教程 webpack 实例')
],
//5.打包模式
mode: 'production',
};
1.Entry:入口文件
entry:字符串|数组|对象
默认只能打包js
module.exports = {
//指定输入文件
//1.字符串:单一js文件
entry:'./src/js/index.js',
//2.数组:多个js文件合成一个
entry:['./src/js/index.js','./src/js/index2.js'],
//3.对象:为每个js文件指定打包名
entry: {
//为每一个js文件命名
first: __dirname + '/src/first.js',
second: __dirname + '/src/second.js',
},
}
- 对象语法
dependOn
: 当前入口所依赖的入口。它们必须在该入口被加载前被加载。filename
: 指定要输出的文件名称。import
: 启动时需加载的模块。library
: 指定 library 选项,为当前 entry 构建一个 library。runtime
: 运行时 chunk 的名字。如果设置了,就会创建一个新的运行时 chunk。在 webpack 5.43.0 之后可将其设为false
以避免一个新的运行时 chunk。publicPath
: 当该入口的输出文件在浏览器中被引用时,为它们指定一个公共 URL 地址。请查看 output.publicPath。
runtime
和dependOn
不应在同一个入口上同时使用
//b2在a2之前被加载
module.exports = {
entry: {
a2: 'dependingfile.js',
b2: {
dependOn: 'a2',
import: './src/app.js',
},
},
};
2.Output:输出文件
filename
:输出的文件名path
:指定输出的路径
- 输出
单个
module.exports = {
output: {
//单一文件,文件输出到 dist 目录中
filename: 'bundle.js',
//单一文件指定输出路径文件名
filename:'js/index.js',
},
};
- 输出
多个
[name]
:会自动指定entry指定的js文件名
[hash]
:随机生成hash值
//输出:./dist/app.js, ./dist/search.js
module.exports = {
entry: {
app: './src/app.js',
search: './src/search.js',
},
output: {
filename: '[name].js',
path: __dirname + '/dist',
},
};
3.Loader:除js外的资源
Webpack本身
只能识别js
。非js文件处理需要用到Loader
- 需要先安装loader 模块
打包css需要用到两个
css-loader
:将css文件变成commonjs模块加载js中,里面内容是样式字符串
style-loader
:创建style标签,将js中的样式资源插入,添加到页面中生效
npm install --save-dev css-loader style-loader
- 配置对应的rules
两种模式
配置指定(推荐)
- loader 从右到左(或从下到上)
例如:打包css需要先用css-loader打包css文件后,用style-loader在页面创建style标签,并将这些文件内容插入
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
/* {
loader: 'css-loader',
options: {
modules: true
}
},*/
]
},
],
},
};
import
!
将资源中的 loader 分开,每部分相当于当前目录解析
import Styles from '!style-loader!css-loader?modules!./styles.css';
!!
前缀,将禁用所有已配置的 loader(preLoader, loader, postLoader)
import Styles from '!!style-loader!css-loader?modules!./styles.css';
-!
前缀,将禁用所有已配置的 preLoader 和 loader,但是不禁用 postLoaders
import Styles from '-!style-loader!css-loader?modules!./styles.css';
4.Plugins:插件
- 插件目的在于
解决 loader 无法实现
的其他事
- 下载插件
npm install html-webpack-plugin -d
- 配置
2.//引入插件
const HtmlWebPackPlugin = require('html-webpack-plugin');
3.配置
//为一个对象类
//1.创建一个空的Html文件,*自动引入*打包好输出的所有资源(js/css)
//一个html指定一个模板
//多个html需要指定多个
const HtmlWebPack = new HtmlWebPackPlugin({
//定义一个html模板,
template: './src/index.html',
//指定输出文件,默认为index.html,不指定时会被覆盖
filename:'index.html',
//压缩
minify:{
//移除空格
collapseWhitespace : true,
//移除注释
removeComments: true,
removeAttributeQuotes: true, //清除多余引号
},
//指定插入模板中的js文件数组队列(entry中定义的名字),
//不匹配将默认全部插入
chunks: [ 'entryName' ],
//生成html文件的favicon的路径
//是否为静态资源添加hash
hash: true
});
4.在插件模块导入
module.exports = {
plugins: [
HtmlWebPack
]
}
5.Mode:打包模式
- 生产:
production
- 开发:
development
实操
打包js
module.exports = {
//指定输入文件(3选一)
//1.字符串:单一js文件
entry:'./src/js/index.js',
//2.数组:多个js文件合成一个
entry:['./src/js/index.js','./src/js/index2.js'],
//3.对象:为每个js文件指定打包名
entry: {
//为每一个js文件命名
'first': __dirname + '/src/first.js',
'second': __dirname + '/src/second.js',
},
//输出文件
output:{
//单一文件指定输出路径文件名
//可以指定路径
filename:'js/index.js',
//多个js文件需要一一指定文件名
//[name]会自动指定entry指定的js文件名,,以及 HtmlWebpackPlugin 插件 中的 chunk 对应
filename: 'js/[name].js',
//输出文件的根目录
path:path.resolve(__dirname,'dist')
}
}
打包样式
less(其他)需要
先转化为css文件然后进行css文件的处理方式
:
less-loader和less(配置时候less不需要写入,只需要写less-loader)
sass-loader依赖于node-sass
module.exports = {
module:{
rules:[
{
test:/\.s(a|c)ss$/,
use:['style-loader','css-loader','sass-loader']
},
]
}
}
分离出css样式为单独文件
mini-css-extract-plugin插件
MiniCssExtractPlugin.loader:替换style-loader实现打包后是以link导入的
module:{
rules:[
{
test:/\.css$/,
use:[
//替换style-loader ,提取js中的css成单独文件
//其他样式也将style-loader替换成这个
MiniCssExtractPligin.loader,
'css-loader'
],
//exclude :/指定不匹配的内容/
}
]
},
plugins:[
new MiniCssExtractPlugin({
//指定输出文件
//这里还可以用[name]等
//这里需要注意不能对文件名使用[hash],不然会导致css的模块热替换失效
filename:'./css/index.css'
})
]
压缩css
//利用插件:optimize-css-assets-webpack-plugin
const OptimizeCssAssetsWebpackPlugin=require('optimize-css-assets-webpack-plugin')
//直接new
plugins:[
new OptimizeCssAssetsWebpackPlugin()
]
打包html
1.下载插件:npm install html-webpack-plugin -D
- 简单用法
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: 'index.js',
output: {
path: __dirname + '/dist',
filename: 'bundle.js'
},
plugins: [
new HtmlWebpackPlugin()
]
}
<!--自动生成一个原始的html文件,自定义需要提供模板-->
<!--打包完后将会生成以下形式,自动将打包生成的js引入-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>
<%=htmlWebpackPlugin.options.title%>
</ title>
<script defer src="index_bundle.js"></script>
</head>
<body>
</body>
</html>
- 复杂用法
//2.引入插件
const HtmlWebPackPlugin = require('html-webpack-plugin');
//为一个对象类
//1.创建一个空的Html文件,*自动引入*打包好输出的所有资源(js/css)
//一个html指定一个模板---------多个html需要指定多个
const HtmlWebPack = new HtmlWebPackPlugin({
//定义一个html模板,(默认为空html模板)
template: './src/index.html',
//指定输出文件,默认为index.html,不指定时会被覆盖
filename:'index.html',
//压缩
minify:{
//移除空格
collapseWhitespace : true,
//移除注释
removeComments: true,
removeAttributeQuotes: true, //清除多余引号
},
//指定插入模板中的js文件数组队列,不匹配将默认全部插入,entry中对象模式的key值
chunks: [ 'chunksName' ],
//生成html文件的favicon的路径
//是否为所包含的脚本和css资源添加hash(有效解决缓存问题)
//为所有js和css等静态资源路径上添加?hash值
hash: true
});
//4.在插件模块导入
module.exports = {
plugins: [
HtmlWebPack
]
}
htmlWebpackPlugin
:相当于这个插件的实例
options
:通过这个获取一些配置信息
打包图片
- webpack5
移除
了4中的url-loader
和file-loader
webpack4
url-loader
的功能类似于file-loader
,但可以在文件小于指定大小时转化为base64编码,可减少Http请求次数,提高访问效率
- 例如小于8kb会被转码,不指定限制的话将全部被转base64
- 超出指定大小将使用
file-loader
打包- 拥有file-loader的全部配置
- 依赖于file-loader,需要一起下载
npm install -D file-loader url-loader
//分两种:css中和html中----------------
module:{
rules:[
//需要解决css打包
{
test:/\.css$/,
use:[ 'style-loader', 'css-loader']},
//-------css文件中的url引用图片资源
{
test:/\.( jpg | png | gif )$/,
//单个loader用法
//url-loader进行打包url-loader是依赖于file-loader(需要两个一起下载)
loader:'url-loader',
//配置
options: {
//小于指定大小会被base64编码,例如小于8kb会被转码//不指定限制的话将全部被转base64
//优:减少请求(减轻服务器压力)
//劣:图片体积会变大,请求速度变慢
limit: 8 * 1024,
//问题:url-loader默认为es6模块化,html-loader引入是commonjs ,在html-loader解析后出现路径为[object Module]
//解决:关闭url-loader的es6模块化 ,使用commonjs
esModule:false
//打包后名字为随机生成的Hash值
//指定hash长度 :[hash:10]:取前十位 [ext]:取原来的扩张名
name: '[hash:10].[ext]' ,
//指定输出文件夹
outputPath:'img'
}
},
//------------------------html文件中的src引用图片资源
{
test:/\.html$/,
//处理html文件的img图片(负责引入img,从而能被url-loadeer进行处理)
loader: 'html-loader'
}
]
}
webpack5
- 资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:
asset/resource
发送一个单独的文件并导出 URL。之前通过使用file-loader
实现。asset/inline
导出一个资源的 data URI。之前通过使用url-loader
实现。asset/source
导出资源的源代码。之前通过使用raw-loader
实现。asset
在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用url-loader
,并且配置资源体积限制实现
在5中使用
url-loader
可能会导致图片打包冲突
在css背景中引入图片会导致又打包了一张图片在根目录(原因是因为
asset module
也打包了一次)需要添加
type: 'javascript/auto'
来自动解决{ test: /\.(png|jpg|jpeg|avg|gif)/, loader: 'url-loader', options: { //。。。 }, type: 'javascript/auto' }
module.exports = {
//输出文件
output: {
//webpack5为资源指定名字
assetModuleFilename: 'images/[name][hash:5][ext][query]'
},
module: {
rules: [
{
test: /\.(png|jpg|jpeg|avg|gif)/,
//其他内容看wepack5官网
type:'asset/resource'
}
]
}
}
同时打包css和html图片
module.exports = {
module: {
rules: [
{
test: /\.css$/,
//配置下MiniCssExtractPlugin.loader,避免出现路劲错误
use: [
//对象模式
{
loader: MiniCssExtractPlugin.loader,
options: {
//在这里设置publicPath的路径就是background-img的路径
//指定公用路径,在当前文件调用文件调用加入前缀
//默认情况下是在webpackOptions.output中使用publicPath
publicPath: '../'
}
},
//普通模式
'css-loader'
]
},
//配置图片----------------------------
{
test: /\.(jpg|png|gif)$/,
loader: 'url-loader',
options: {
//不指定限制的话将全部被转base64
limit: 8 * 1024,
//指定文件夹
outputPath: 'img',
esModule: false,
//指出公用的路径,在调用时以这个为根路径调用,需要与输出路径配合
// publicPath:'assets/img',
}
},
//打包html中的-------------------------
//处理html文件的img图片(负责引入img,从而被url-loader进行处理)
{
test: /\.html$/,
loader: 'html-loader',
}
]
},
}
打包其他资源
//------打包除html,css,js,图片等其他资源,例如阿里的图标文字类
module:{
rules:[
//排除法
{
exclude:/\.(css | js | html | less | png | jpg | gif)$/,
loader: 'file-loader',
options:{
name:'[hash:10].[ext]' ,
//指定输出文件夹
outputPath:'media'
}
},
]
}
自动化
//------使用devServer实现自动化(热编译,自动编译,自动打开浏览器,自动刷新)
//-----------需要webpack-dev-server包支持
//-------------局部安装时启动devServer:npx webpack-dev-server
const Webpack = require("webpack")
module.exports={
devServer:{
//静态资源的根目录
//webpack5改为了static
contentBase : path.resolve(_dirname,'dist'),
//启动gzip压缩
compress : true,
//指定端口号(注意端口,避免出错)
port : 8888,
//自动打开浏览器
open:true,
//开启模块热替换
hot:true
},
plugins: [
new OptimizeCssAssetsWebpackPlugin(),
// 启动热更新功能插件
//只修改更新的内容,无需刷新页面
new Webpack.HotModuleReplacementPlugin(),
// 帮助减少不需要的信息展示
new Webpack.NoEmitOnErrorsPlugin()
],
}
配置SourceMap(源代码映射)
实现代码的打包成果(打包后分为原代码(便于定位错误),编过的等,详情看devtool配置)
devtool:"对用的模式",
///
----none//默认,适用于生产
eval//生成后的代码
cheap-eval-source-map//转换过的代码
---cheap-module-eval-source-map//用于开发环境
分开环境配置
--config 指定运行的文件
创建webpack.dev.js
和webpack.prod.js
抽离根据环境配置,然后修改npm脚本命令指定打包的时候运行对应的配置文件
"scripts":{
"dev":"webpack-dev-server --config ./webpack.dev.js",
"build":"webpack --config ./webpack.prod.js"
}
抽离公共配置代码
-
安装webpack-merge抽离重复代码
//引入抽离的公共代码 const baseConfig = require("./xxxx"); //引入工具 const merge = require("webpack-merge"); //单独配置信息 const prodConfig = { //.... plugins: [ //这里和公共配置文件同时使用了HtmlWebpackPlugin,直接用merge合并打包时候会出错,合并的时候需要用提供的mergeWithCustomize自定义字段 new HtmlWebpackPlugin({ //... minify:{ collapseWhitespace:true,//清除空格 removeComments:true,//移除注释 removeAttributeQuotes:true,//清除多余引号 }, //为所有js和css等静态资源路径上添加?hash值 //有效解决缓存问题 hash:true }), } //导出合并后的 module.exports = merge(baseConfig,prodConfig);
-
保持插件的唯一性,采用自定义字段(例如默认配置文件和生产配置文件同时用到了
HtmlWebpackPlugin
,这样会报错) -
解决
HtmlWebpackPlugin
(插件)重复出现的错误/** * mergeWithCustomize:实现自定义字段 * --------------- * unique是一种用于在配置中强制唯一性的策略。 * - 确保插件唯一性 * - 并且是最后一个插件实例 * 参数:1.查找的config字段,2.要去重的config下的字段,3.输出返回一个插件 */ //下面实现用当前配置文件的HtmlWebpackPlugin const webpackConfig = mergeWithCustomize({ customizeArray: unique( "plugins", ["HtmlWebpackPlugin"], (plugin) => plugin.constructor && plugin.constructor.name ), })( BaseConfig, ProdConfig ); module.exports = webpackConfig
解析ES6语法
部分低版本浏览器不支持es6语法
- 需要用
babel
将es6转化为es5
- 安装
npm install --save-dev babel-loader @babel/core
- 配置规则
{
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
- 实际做转化的是
@babel/preset-env
,安装
npm install --save-dev @babel/preset-env
- 根目录创建
babel.config.json
配置启动一些预设
{
"presets": ["@babel/preset-env"]
}
打包iconfont
- 创建
src/assets/iconfont
,将阿里矢量图标下载的内容放入(下载对应图标,下载提供的demo有对应的使用说明)
module.exports = {
module: {
rules: [
{
test: /\.(woff2|woff|ttf)$/,
loader: "url-loader",
options: {
name: "[name][hash:5].[ext]",
limit: 1024,
outputPath: "icon",
esModule: false,
// publicPath: "../"
},
type: "javascript/auto"
}
]
}
}
sass和less的全局问题
使用
sass-resources-loader
可以使得在所用sass(less)共享全局变量、mixin和函数等。不再需要一个个去加载他们。
npm i -D sass-resources-loader
module.exports = {
module: {
{
test: /\.s(a|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: "../"
}
},
"css-loader",
"postcss-loader",
"sass-loader",
{
//先用sass-resources-loader处理
loader:"sass-resources-loader",
options:{
//指定全局样式文件路径(数组)
resources:[path.resolve(__dirname,"src/assets/style/global.scss")]
}
}
]
},
}
}
vue-cli中则需要用到预处理器 Loader
// vue.config.js module.exports = { css: { loaderOptions: { // 给 sass-loader 传递选项 sass: { // @/ 是 src/ 的别名 // 所以这里假设你有 `src/variables.sass` 这个文件 // 注意:在 sass-loader v8 中,这个选项名是 "prependData" additionalData: `@import "~@/variables.sass"` }, } }
拷贝文件插件
copy-webpack-plugin
const copyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
plugins:[
new CopyPlugin([
{
from:'哪里(可*多个)',
to:'拷贝到哪里'
}
])
]
}
new CopyPlugin({
patterns:[{
from:'哪里(可*多个)',
to:'拷贝到哪里'
}]
})
拷贝static下的文件
- 这里下载低版本(新版本会报错)
npm i -D copy-webpack-plugin@9.*
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
plugins: [
new CopyWebpackPlugin({
patterns: [
{
from: path.resolve(__dirname,"src/static"),
to: path.resolve(__dirname,"dist/static"),
},
],
}),
]
}
打包分析
webpack-bundle-analyzer
设置别名,指定引入的包是指定包下的
Vue打包下生成三个文件:
//运行时版本
- rentime only 的文件 vue.common.js
//编译时版本
- compiler only 的文件compiler.js
//平时时候用的版本
- runtime+compiler的文件vue.js
resolve:{
alias:{
//在导入vue的时候指定加载包
'vue':'vue/dist/vue.js'
}
}
错误集合
- 模块热替换报
Maximum call stack size exceeded
因为package.json中配置的脚本写了
webpack-dev-server --hot
,--hot
与webpack.config.js中new webpack.HotModuleReplacementPlugin()两者冲突,删除一个
- css模块热替换失效
由于设置了[hash]
new MiniCssExtractPlugin({
//指定输出文件
//这里还可以用[name]等
//这里需要注意不能对文件名使用[hash],不然会导致css的模块热替换失效
filename:'./css/index.css'
//下面这条导致css热替换失效
// filename:'./css/[name][hash:5].css'
})
- 出现:
ERROR in Conflict: Multiple assets emit different content to the same filename index.html
- HtmlWebpackPlugin是否设置了
filename
字段(默认设置为index.html)(设置多次HtmlWebpackPlugin的时候需要单独指名)- 使用
webpack-merge
合并配置文件的时候同时设置了HtmlWebpackPlugin,导致认为要多文件输出,单需要唯一时候,需要用mergeWithCustomize
自定义字段
- sass(less)全局变量问题
- 需要用 sass-resources-loader处理
- vue-cli需要配置css预处理