前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >webpack5学习笔记

webpack5学习笔记

原创
作者头像
代码哈士奇
发布2022-01-26 19:54:20
2.4K0
发布2022-01-26 19:54:20
举报
文章被收录于专栏:dmhsq_csdn_blogdmhsq_csdn_blog

webpack5学习笔记

看的是b站的千峰教育的视频 感觉很不错

千峰课程视频

cdn资源 cdn资源

webpack官网

webpack插件

webpack笔记

解决作用域问题

快速执行函数

;(function(){

代码语言:txt
复制
.....

})

解决代码拆分问题

node

commonjs

模块化

解决浏览器支持问题

requirejs

想要主js调用别的js要在主js前引入

hello.js

export hello()

main.js

hello()

import hello.js

import main.js

安装webpack

先安装node

然后安装webpack webpack-cli 全局安装(不推荐,会锁定版本)

npm install webpack webpack-cli --global

本地安装

代码语言:txt
复制
npm init 
npm install webpack webpack-cli --save-dev 

cmd cls清屏

webpack打包

代码语言:txt
复制
webpack

webpack --stats detailed 查看详细打包信息

npx牛逼

配置入口文件(指令不如文件配置不可保存)

webpack --entry xxx

加 --mode production生产环境

配置出口

output

文件配置

webpack.config.js文件

绝对路径 使用 require('path')

代码语言:txt
复制
path.resolve(__dirname,'xxx')

module.exports = {
	entry:'',
	
	output:{
		filename: '',
		path: '结对路径''
	}
	
	
}

自动引入资源

插件-html-webpack-plugin
代码语言:txt
复制
npm install html-webpack-plugin

引入

代码语言:txt
复制
const HtmlWebpackPlugin = require('html-webpack-plugin') 

在根{}下

代码语言:txt
复制
plugins:[
	new HtmlWebpackPlugin()
]

配置HtmlWebpackPlugin
new HtmlWebpackPlugin({
	template: './index.html', 模板文件
	filename: 'app.html', 生成文件名
	inject: 'body' 在哪个标签引入
})
清理dist(清理旧的打包)

在output选项里面

代码语言:txt
复制
output:{
		filename: '',
		path: '结对路径'',
		clean: true
	}

搭建开发环境

mode选项
定位错误

更好显示代码定位错误

代码语言:txt
复制
devtool: 'inline-source-map',
监听代码变化
代码语言:txt
复制
webpack --watch
使用 webpack-dev-server
代码语言:txt
复制
npm install webpack-dev-server

加-D 在本地开发环境运行

在 配置文件中

代码语言:txt
复制
devServer: {
	devServer: {
		static: './dist'  //注意这里的./dist是路径
	}
}

在控制台 webpack-dev-server

资源模块

代码语言:txt
复制
module: {
		rules: [
			{
				test: /\.png$/,
				type: 'asset/resource'
			}
		]
	}

在js 文件中引入

代码语言:txt
复制
import imgsrc from './assets/img-1.png'

const img = document.createElement('img') 创建一个照片元素
img.src = imgsrc 添加路径
document.body.appendChild(img) 将照片添加进页面

webpack-dev-server --open 加--open 默认打开

在output中定义导出路径以及名字

代码语言:txt
复制
output: {
		filename: 'bundle.js',
		path: path.resolve(__dirname,'./dist'),
		clean: true,
		assetModuleFilename: 'images/test.png'
	},

assetModuleFilename: 'images/contenthash.png'

contenthash可自动根据hash来生成文件名

assetModuleFilename: 'images/contenthash'

contenthash可自动根据hash来生成文件名以及扩展名

若在module rules generator配置

则generator高于output

inline配置资源 使图片变成base64资源

使图片变成base64资源

代码语言:txt
复制
test: /\.svg$/,
type: 'asset/inline'
配置source
代码语言:txt
复制
test: /\.txt$/,
type: 'asset/source
配置asset
代码语言:txt
复制
test: /\.jpg$/,
type: 'asset'

自动选择url还是文件base64 一般小于8k会生成base64

可通过追加 parser 来控制

代码语言:txt
复制
test: /\.jpg$/,
type: 'asset',
parser: {
    dataUrlCondition: {
        maxSize: 4*1024  //默认大小4*1024 
    }
}

loader使用

安装css-loader以及style-loader

执行

代码语言:txt
复制
npm install css-loader -D

npm install style-loader -D

配置

代码语言:txt
复制
{
    test: /\.css$/,
    use: ['style-loader','css-loader']
}

在index.js引入

import './style.css'

先执行css-loader再执行style-loader

安装配置less-loader css-loader
代码语言:txt
复制
npm install less-loader less -D

配置

代码语言:txt
复制
{
    test: /\.(css|less)$/,
    use: ['style-loader','css-loader','less-loader']
}

在index.js引入

import './style.less'

抽离和压缩css

安装插件

代码语言:txt
复制
npm install mini-css-extract-plugin -D

在webpack.js引入

const MiniCssExtract = require('mini-css-extract-plugin')

在plugins中添加

new MiniCssExtract()

配置

代码语言:txt
复制
{
    test: /\.(css|less)$/,
    use: [MiniCssExtract.loader','css-loader','less-loader']
}

更换style-loader为MiniCssExtract.loader

style-loader作用是将css连接到页面

而为了抽离改为MiniCssExtract.loader

自定义生成的文件名

new MiniCssExtract({

代码语言:txt
复制
filename: 'styles/[contenthash].css'

})

压缩

安装插件

代码语言:txt
复制
npm install css-minimizer-webpack-plugin -D

引入

const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')

在优化配置中配置

webpack配置根级

代码语言:txt
复制
optimization: {
	minimizer: [
		new CssMinimizerPlugin()
	]
}

注意配置此项之后 代码压缩会失效 需要单独配置terser

且mode更换为生产环境

mode: 'production',

加载images图像
图片优先级

.block-bg{

代码语言:txt
复制
background-image: url(./assets/webpack-logo.svg) !important;

}

!important 使优先级最高

加载字体

配置webpack

代码语言:txt
复制
{
    test: /\.(woff|woff2|eot|ttf|otf)$/,
    type: 'asset/resource'
}

在css文件引入字体文件

代码语言:txt
复制
@font-face {
    font-family: 'iconfont';
    src: url('./assets/iconfont.ttf');
}

.icon{
    font-family: 'iconfont';
    font-size: 30px;
}

在index.js引入字体

代码语言:txt
复制
const span = document.createElement('span')

span.classList.add('icon')
span.innerHTML = ''
document.body.appendChild(span)
加载数据 csv-loader xml-loader

安装

代码语言:txt
复制
npm install csv-loader xml-loader -D

配置

代码语言:txt
复制
{
    test: /\.(csv|tsv)$/,
    usr: 'csv-loader'
},

{
    test: /\.xml$/,
    usr: 'xml-loader'
}

引入数据在index.js

代码语言:txt
复制
import Data from './assets/data.xml'
import Notes from './assets/data.csv'

xml转成js对象

csv转换为数组

自定义JSON的parser 例如toml yaml json5

安装

代码语言:txt
复制
npm install toml yaml json5 -D

配置webpack

代码语言:txt
复制
const toml = require('toml')
const yaml =require('yaml')
const json5 = require('json5')
代码语言:txt
复制
{
	test: /\.toml$/,
	type: 'json',
	parser: {
		parse: toml.parse
	}
},

{
	test: /\.yaml$/,
	type: 'json',
	parser: {
		parse: yaml.parse
	}
},

{
	test: /\.json5$/,
	type: 'json',
	parser: {
		parse: json5.parse
	}
}

使用文件

babel-loader

将es6转化为es5

babel-loader:在webpack解析es6

@babel/core:babel核心模块

@babel/preset-env:babel预定,一组babel插件的集合

安装
代码语言:txt
复制
npm install -D babel-loader @babel/core @babel/preset-env
配置

{

代码语言:txt
复制
test: /\.js$/,
代码语言:txt
复制
exclude: /node_modules/,
代码语言:txt
复制
use: {
代码语言:txt
复制
	loader: 'babel-loader',
代码语言:txt
复制
	options: {
代码语言:txt
复制
		presets: ['@babel/preset-env']
代码语言:txt
复制
	}
代码语言:txt
复制
}

}

解决报错regeneratorRuntime

原因 babel生产用于兼容async/await

安装插件 @babel/runtime

代码语言:txt
复制
npm install @babel/runtime -D

安装插件 @babel/plugin-transform-runtime

代码语言:txt
复制
npm install @babel/plugin-transform-runtime -D

配置

代码语言:txt
复制
{
	test: /\.js$/,
	exclude: /node_modules/,
	use: {
		loader: 'babel-loader',
		options: {
			presets: ['@babel/preset-env'],
			plugins: [
				['@babel/plugin-transform-runtime']
			]
		}
	}
}

分离代码

如果有多个入口文件

代码语言:txt
复制
entry: {
	index: './src/index.js',
	another: './src/another-module.js'
},

出口的filename: '[name].bundle.js',

但是这样会导致重复打包

避免重复
方案一 共享
代码语言:txt
复制
entry: {
	index: {
		import: './src/index.js',
		dependOn: 'shared'
	},
	another: {
		import: './src/another-module.js',
		dependOn: 'shared'
	},

	shared: 'lodash'
},
方案二 配置splitChunks

optimization: {

代码语言:txt
复制
splitChunks: {
代码语言:txt
复制
	chunks: 'all'
代码语言:txt
复制
}

}

动态(异步)导入

如下

代码语言:txt
复制
function getComponent() {
    return import('lodash')
        .then(({default: _})=>{
            const element = document.createElement('div')
            element.innerHTML = _.join(['hello','webpack'],' ')
            return element
        })
}

getComponent().then((element)=>{
    document.body.appendChild(element)
})


const button = document.createElement('button')
懒加载
代码语言:txt
复制
button.textContent = '点击加法运算'
button.addEventListener('click',()=>{
    import(/* webpackChunkName: 'math' */'./math').then(({add})=>{
        console.log(add(4,5))
    })
})

document.body.appendChild(button)

import(/ webpackChunkName: 'math' /'./math')魔法注释 可以设置打包文件名

预加载预获取

prefetch 浏览器空闲时加载

import(/ webpackPrefetch: true /

preload 类似懒加载

import(/ webpackPreload: true /

缓存

输出文件名

filename: 'name.contenthash.js',

缓存第三方库
代码语言:txt
复制
optimization: {
	minimizer: [
		new CssMinimizerPlugin()
	],

	splitChunks: {
		cacheGroups: {
			vendor: {
				test: /[\\/]node_modules[\\/]/,
				name: 'vendors',
				chunks: 'all'
			}
		}
	}
}
js放到一个文件夹

output: {

代码语言:txt
复制
	filename: 'scripts/[name].[contenthash].js',
代码语言:txt
复制
	....

开发配置

公共路径

在output中

加入publicPath: 'http://localhost:8080/'

环境变量

module.exports = (env) => {

代码语言:txt
复制
console.log(env)
代码语言:txt
复制
return {
代码语言:txt
复制
    webpack配置项 可通过env参数配置
代码语言:txt
复制
}

}

比如

mode: env.production ? 'production' :'development'

webpack --env production

可以传参 a = 1

压缩代码 使用terser-webpack-plugin -D
代码语言:txt
复制
npm install terser-webpack-plugin -D

使用

代码语言:txt
复制
optimization: {
		minimizer: [
			new CssMinimizerPlugin(),
			new TerserPlugin()
		],
...
拆分配置文件

开发环境和生产环境

开发环境

项目根目录新建webpack.config.dev.js 开发环境

修改mode为开发环境

去掉压缩代码以及公共路径或包括缓存

启动

webpack -c ./config/webpack.config.dev.js

-c可用 -config替换

注意生成的文件的路径

生产环境

在config目录下新建 webpack.config.prod.js文件

修改mode为生产环境

删除调试 devtool dev-server

启动

webpack -c ./config/webpack.config.prod.js

额外webpack serve (webpack-dev-server)

可通过 webpack serve -c ./config/webpack.config.dev.js

npm 脚本

在项目根目录下 package.json

代码语言:txt
复制
{
  "scripts": {
    "start": "npx webpack server -c ./config/webpack.config.dev.js",
    "build": "npx webpack -c ./config/webpack.config.prod.js"
  }
}
忽略性能优化提示

在webpack配置根{}下

performance: {

代码语言:txt
复制
hints: false

}

提取公共配置

项目根目录创建webpack.config.common.js文件

去除掉 dev prod中相同配置

合并配置文件 使用webpack-merge

安装

代码语言:txt
复制
npm install webpack-merge -D

config目录下创建 wenpacj.config.js

代码语言:txt
复制
const { merge } = require('webpack-merge')

const commonConfig = require('./webpack.config.common')
const productionConfig = require('./webpack.config.prod')
const developmentConfig = require('./webpack.config.dev')

module.exports = (env) => {
    switch (true) { //可定义key-value判断
        case env.development:
            return merge(commonConfig,developmentConfig)

        case env.production:
            return merge(commonConfig,productionConfig)

        default:
            return new Error('No matching configuration was found')
    }
}

source-map

新建目录 npm init 初始化

安装 npm install webpack webpack-cli webpack-dev-server html-webpack-plugin -D

默认devtool为eval

'source-map'

会生产main.js.map 且生产的main.js注释里会显示sourceUrl main.js.map(显示行列) 且关联

能找到代码问题

'hidden-source-map'

会生产main.js.map 且生产的main.js注释里不会显示sourceUrl main.js.map 且不关联

不能直接找到代码问题

'inline-source-map'

不会生产main.js.map 但生产的main.js注释里会显示sourceUrl main.js.map 且关联

能找到代码问题

'eval-source-map'

不会生成sourcemap文件 而是放到了eval后面

能找到代码问题

'cheap-source-map'

生成map文件 mappings带有行数不带列

能找到代码问题

'cheap-module-source-map' 推荐开发环境

生成map文件 mappings带有行数不带列 带有module的

能找到代码问题

webpack-server 配置

代码语言:txt
复制
devServer: {
	static: path.resolve(__dirname, './dist'),
	compress: true, //代码压缩 增加gzip
	port: 3000, //端口号
	host: '0.0.0.0', //局域网下可访问

	headers: {
		'X-Access-Token': 'abc123'
	},

	proxy: { //代理配置
		'/api': 'http://localhost:9000'
	},

	// https: true, //开启https
	// {
	//     cacert: './server/pem',
	//     pfx: './server.pfx',
	//     key: './server.key',
	//     cert: './server.crt',
	//     passphrase: 'webpack-dev-server',
	//     requestCert: true
	// }



	http2: true, //开启 http2 https默认自签名

	historyApiFallback: true //历史路径

}

模块热替换和热加载

热替换

hmr在webpack5不需要再繁琐配置 疫情开箱即用

代码语言:javascript
复制
devServer: {
    hot: true    
}

修改js热更新

在app.js

代码语言:javascript
复制
if(module.hot){
    module.hot.accept('./input.js', () => {
        
    })
}
热加载
代码语言:javascript
复制
devServer: {
    liveReload: true
}
代码规范 eslint
安装
代码语言:txt
复制
npm i eslint -D
代码语言:txt
复制
eslint ./src
项目使用
代码语言:javascript
复制
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    mode: 'development',

    entry: './src/app.js',

    module: {
        rules: [
            {
                test: /\.js$/,
                usr: ['babel-loader','eslint-loader'] //先eslint-loader'
            },
        ],
    },

    plugins: [
        new HtmlWebpackPlugin()
    ]
};

开启后可关闭报错

代码语言:javascript
复制
devServer: {
    client: {
        overlay: false //报错覆盖层
    }
}
Githooks--Husky

目的 提交之前检测代码

基本原理

.git/hooks/pre-commit文件

文件内容

代码语言:txt
复制
eslint ./src
或者
npx eslint ./src
自定义

新建目录 .mygithooks

文件 .mygithooks/pre-commit 内容一样

git 配置

git config core.hooksPath .mygithoosk

Husky
代码语言:txt
复制
npm husky install -D

huxky install


package.json
 "main": "index.js",
  "scripts": {
    "prepare": "husky install"
  },

在./husky目录下 新增pre-commit文件

记得给予 pre-commit 文件权限 (+x)

写入 npx eslint .src

执行

git add.

git commit -m 'xxx'

如果代码出错会提示

探索webpack原理

解析绝对目录

别名配置

用@ 指向 src

webpack.js

代码语言:javascript
复制
resolve: {
  alias: {
    '@': path.resolve(__dirname,'./src')
  }
}
优先级配置 默认 js>json

配置

代码语言:javascript
复制
resolve: {
  alias: {
    '@': path.resolve(__dirname,'./src')
  },
  extensions: ['.json','.js','vue']
}
配置外部资源引入(链接引入)
方式一

wepack配置文件

代码语言:javascript
复制
externals: {
  jquery: 'jQuery'
}

在html模板文件里面加入

代码语言:txt
复制
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
方式二

wepack配置文件

代码语言:javascript
复制
externalsType: 'script', //暴露为script标签
externals: {
  jquery: [
    'https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js', //链接
    '$' //暴露标签
  ]
}
依赖图

安装

代码语言:txt
复制
npm i webpack-bundle-analyzer -D

引入

代码语言:javascript
复制
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')

plugins: [
    new BundleAnalyzerPlugin()
  ]

启动webpack serve就会弹出

PostCSS和CSS模块 处理浏览器css兼容问题

安装

npm i postcss-loader -D

npm i autoprefixer -D

配置 webpack
代码语言:javascript
复制
module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader', 'postcss-loader']
      }
    ]
  }
配置 postcss.config.js

在根目录下创建文件

代码语言:javascript
复制
module.exports = {
  plugins: [
    require('autoprefixer')
  ]
}
使用

在package.json目录下 根{}

代码语言:json
复制
"browserslist": [
    "> 1%", //全球浏览器使用率要大于1%
    "last 2 versions" //每个浏览器的最近两个版本
  ]
插件 postcss-nested

支持比如 body下包括div的 这种

安装

npm i postcss-nested -D

配置postcss.config.js

代码语言:txt
复制
module.exports = {
  plugins: [
    require('autoprefixer'),
    require('postcss-nested')
  ]
}

开启css模块化

代码语言:javascript
复制
use: ['style-loader',
  {
    loader: 'css-loader',
    options: {
    modules: true  //开启css模块化
  }
 }
, 'postcss-loader'],
exclude: [path.resolve(__dirname,'..','node_modules')] //排除外部modules

可设置两个配置 一个全局一个局部

如下 在webpack配置

全局配置

代码语言:javascript
复制
{
  test: new RegExp(`^(?!.*\\.global).*\\css`),
    use: ['style-loader',
      {
        loader: 'css-loader',
        options: {
        modules: true  //开启css模块化
      }
     }
    , 'postcss-loader'],
    exclude: [path.resolve(__dirname,'..','node_modules')] //排除外部modules
}

局部配置

代码语言:javascript
复制
{
  test: new RegExp(`^(.*\\.global).*\\css`),
    use: [
      {
        loader: 'style-loader'
      },
      {
        loader: 'css-loader'
      },
      {
        loader: 'postcss-loader'
      }
      ],
    exclude: [path.resolve(__dirname,'..','node_modules')] //排除外部modules
}

WebWorks

创建一个worker

const worker = new Worker(new URL('./work.js',import.meta.url))

接收主线程信息

self.onmessage = () => {

}

主线程接收信息

worker.onmessage = (message) => {

console.log(message)

}

向主线程发送信息

self.postMessage({

代码语言:txt
复制
answer: 1111

})

主线程发送信息

worker.postMessage({

question: 'hi,那边的worker线程,请告诉我今天的幸运数字是多少?'

})

集成typescript

安装

代码语言:txt
复制
npm i typescript ts-loader -D

配置 webpack

代码语言:javascript
复制
const HtmlWebpackPlugin = require('html-webpack-plugin')
const path = require('path')
module.exports = {
  mode: 'development',
  entry: './src/app.ts',
  devtool: 'inline-source-map',
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: 'ts-loader',
        exclude: /node_modules/
      }
    ]
  },


  resolve: {
    extensions: ['.ts', '.js']  //设置优先ts扩展名
  },

  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, './dist')
  },
  
  plugins: [
    new HtmlWebpackPlugin()
  ]

}

初始化ts配置文件

代码语言:txt
复制
tsc --init

修改ts配置

rootDir: "./src"

outDir: "./dist"

ts 使用模块

网址 https://www.typescriptlang.org/dt/search?search=

查询需求模块安装

entry 配置

配置一
代码语言:javascript
复制
entry: [
    './src/app.js',
    './src/app2.js'
  ]
配置二
代码语言:javascript
复制
// entry: [
  //   './src/app.js',
  //   './src/app2.js',
  //   'lodash'
  // ],

  entry: {
    main: ['./src/app2.js', './src/app.js'],
    lodash: 'lodash'
  },
配置三
代码语言:javascript
复制
entry: {
    main: {
      import: ['./src/app2.js', './src/app.js'],
      dependOn: 'lodash' //依赖
    },
    lodash: 'lodash'
  },

index.html模板配置

配置一 基础配置

webpack

代码语言:javascript
复制
 plugins: [
    new HtmlWebpackPlugin({
      title: '多页面应用', //参数
      template: './index.html',
      inject: 'body', //引入js的地方
      chunks: ['main'] //规定引入的js
    })
  ]
代码语言:html
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>

</body>
</html>
配置二

多页面配置

代码语言:javascript
复制
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  mode: 'development',

  // entry: [
  //   './src/app.js',
  //   './src/app2.js',
  //   'lodash'
  // ],

  entry: {
    main: {
      import: ['./src/app2.js', './src/app.js'],
      dependOn: 'lodash',
      filename: 'chanel1/[name].js'
    },
    main2: {
      import: './src/app3.js',
      dependOn: 'lodash',
      filename: 'chanel2/[name].js'
    },
    lodash: {
      import: 'lodash',
      filename: 'common/[name].js'
    }
  },

  output: {
    clean: true
  },


  plugins: [
    new HtmlWebpackPlugin({
      title: '多页面应用',
      template: './index.html',
      inject: 'body',
      filename: 'chanel1/index.html',
      chunks: ['main', 'lodash'],
      publicPath: 'http://www.b.com'
    }),

    new HtmlWebpackPlugin({
      template: './index2.html',
      inject: 'body',
      filename: 'chanel2/index2.html',
      chunks: ['main2', 'lodash'],
      publicPath: 'http://www.a.com'
    })
  ]


}

Tree Shaking

移除未使用模块

配置一 usedExports

es2015特性

但是无法额外模块

配置webpack

代码语言:javascript
复制
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  mode: 'production',
  entry: './src/app.js',
  plugins: [
    new HtmlWebpackPlugin()
  ],

  optimization: {
    usedExports :true //此处开启
  }
}
配置二 sideEffects

在packages.json配置

代码语言:json
复制
{
  "sideEffects": true, //true都加载 false都不加载
  "sideEffects": ["*.css"], //对于所有的css文件都加载,其它不加载
  "sideEffects": ["*.css", "*.global.js"],//对于所有的css文件以及.global.js文件都加载,其它不加载
}

离线环境下运行

非离线环境下运行

打包完成

安装 http-server

代码语言:txt
复制
npm i http-server -D

配置 packages.json

代码语言:txt
复制
"scripts": {
    "start": "http-server dist"
  },
使webpack serve 运行时变动打包而不是内存

webpack 配置

代码语言:txt
复制
devServer: {
    devMiddleware: {
      writeToDisk: true
    }
  }
添加workbox 实现pwa

安装

代码语言:txt
复制
npm i workbox-webpack-plugin -D

配置

代码语言:txt
复制
const HtmlWebpackPlugin = require('html-webpack-plugin')
const WorkboxPlugin = require('workbox-webpack-plugin')

module.exports = {
  mode: 'production',
  entry: './src/app.js',
  plugins: [
    new HtmlWebpackPlugin(),
    new WorkboxPlugin.GenerateSW({
      clientsClaim: true,
      skipWaiting: true
    })
  ],
浏览器注册

入口文件

app.js

代码语言:txt
复制
if ('serviceWorker' in navigator) { //浏览器是否支持
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/service-worker.js')
      .then(registration => {
        console.log("SW 注册成功")
        console.log(registration)
      })
      .catch(registrationError => {
        console.log("SW 注册失败", registrationError)
      })
  })
}

shimming 全局变量

webpack配置

代码语言:javascript
复制
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  plugins:[
    new HtmlWebpackPlugin(),
    new webpack.ProvidePlugin({
      _: 'lodash'
    })
  ]
}

使用 index.js

代码语言:javascript
复制
// import _ from 'lodash' //无需引入

console.log(_.join(['hello', 'webpack'], ' '))

细颗粒度 shimming

this问题 imports-loader

安装

代码语言:txt
复制
npm i imports-loader -D

配置webpack

代码语言:txt
复制
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  plugins:[
    new HtmlWebpackPlugin(),
    new webpack.ProvidePlugin({
      _: 'lodash'
    })
  ],
  module: {
    rules: [
      {
        test: require.resolve('./src/index.js'),
        use: 'imports-loader?wrapper=window' //让包里的this指向window
      }
    ]
  }
}

全局exports

插件 exports-loader

代码语言:txt
复制
npm i exports-loader -D

使用 webpack配置

代码语言:javascript
复制
module: {
    rules: [
      {
        test: require.resolve('./src/index.js'),
        use: 'imports-loader?wrapper=window'
      },
      {
        test: require.resolve('./src/global.js'),
        use: 'exports-loader?type=commonjs&exports=file,multiple|helpers.parse|parse' //相当于暴露parse:helper.parse
      }
    ]
  }

polyfills 垫片

简单原理

不能这样引入

安装 @babel/polyfill

代码语言:txt
复制
npm i @babel/polyfill -D
代码语言:javascript
复制
import '@babel/polyfill' //垫片  这样导入 X

console.log(Array.from([1, 2, 3], x => x + x))
进一步优化

安装babel环境

代码语言:txt
复制
npm i babel-loader @babel/core @babel/preset-env -D

配置webpack

代码语言:txt
复制
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  mode: 'development',
  entry: './src/index.js',

  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              [
                '@babel/preset-env',
                {
                  targets: [
                    'last 1 version', //浏览器最新的一个版本
                    '> 1%' //代码使用超过1%
                  ],
                  useBuiltIns: 'usage',
                  corejs: 3
                }
              ]
            ]
          }
        }
      }
    ]
  }

}

额外安装

代码语言:txt
复制
npm install --save core-js@3

library

打包配置为不同模块
代码语言:txt
复制
const path = require('path')

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  experiments: {
    outputModule:true // module时候开启此配置
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'mylib.js',
    library: {
      // name: 'mylib', // module时候取消此配置
      type: 'module'  // window/commonjs/module
    }
  }
}
打包为通用模块
代码语言:txt
复制
const path = require('path')

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  // experiments: {
  //   outputModule:true // module时候开启此配置
  // },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'mylib.js',
    library: {
      // name: 'mylib', // module时候取消此配置
      type: 'umd'  // window/commonjs/module/umd
    },
    globalObject: 'globalThis' //全局this代替self
  }
}
构建小轮子

配置

代码语言:javascript
复制
const path = require('path')

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'webpack-numbers.js',
    library: {
      name: 'webpackNumbers',
      type: 'umd'
    },
    globalObject: 'globalThis'
  },
  externals: { //优化依赖
    lodash: {
      commonjs: 'lodash',
      commonjs2: 'lodash',
      amd: 'lodash',
      root: '_'
    }
  }

}

发布为 npm-package

执行

npm config get registry

确保为

"https://registry.npmjs.org/"

如果不是 切换 npm set registry "https://registry.npmjs.org/"

npm adduser 添加用户

npm publish 发布

模块联邦 多项目共享模块

使用webpack 的 ModuleFederationPlugin

先准备好两个模块

模块nav

组件js Header.js

代码语言:javascript
复制
const Header = () =>{
  const header = document.createElement('h1')
  header.textContent = '公共头部内容'
  return header
}

export default Header

webpack配置项

代码语言:javascript
复制
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { ModuleFederationPlugin } = require('webpack').container


module.exports = {
  mode: 'production',
  entry: './src/index.js',
  plugins: [
    new HtmlWebpackPlugin(),

    new ModuleFederationPlugin({
      name: 'nav', //模块名
      filename: 'remoteEntry.js', //模块文件名
      remotes: {}, //引入的模块
      exposes: { //导出的模块
        './Header': './src/Header.js' //模块路径
      },
      shared: {} //共享包
    })
  ]

}
模块home引入 nav

webpack配置项

代码语言:javascript
复制
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { ModuleFederationPlugin } = require('webpack').container

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  plugins: [
    new HtmlWebpackPlugin(),

    new ModuleFederationPlugin({
      name: 'home', //模块名
      filename: 'remoteEntry.js', //模块文件名
      remotes: { //引入的模块
        nav: 'nav@http://localhost:3003/remoteEntry.js' //网络位置
      },
      exposes: {}, //导出的模块
      shared: {} //共享包
    })
  ]
}

使用nav下的Header

异步加载

代码语言:javascript
复制
import HomeList from "./HomeList";

import('nav/Header').then((Header)=>{
  const body = document.createElement('div')
  body.appendChild(Header.default())
  document.body.appendChild(body)
  document.body.innerHTML += HomeList(5)
})
模块 search 引入两个资源

暴露 home的homeList组件

代码语言:javascript
复制
new ModuleFederationPlugin({
      name: 'home',
      filename: 'remoteEntry.js',
      remotes: {
        nav: 'nav@http://localhost:3003/remoteEntry.js'
      },
      exposes: {
        './HomeList': './src/HomeList.js'
      },
      shared: {}
    })

在webpack配置项引入

代码语言:javascript
复制
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { ModuleFederationPlugin } = require('webpack').container

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  plugins: [
    new HtmlWebpackPlugin(),

    new ModuleFederationPlugin({
      name: 'search',
      filename: 'remoteEntry.js',
      remotes: {
        nav: 'nav@http://localhost:3003/remoteEntry.js',
        home: 'home@http://localhost:3001/remoteEntry.js'
      }
    })
  ]
}

在 search 中引入 index.js

代码语言:javascript
复制
Promise.all([import('nav/Header'),import('home/HomeList')])
  .then(([
    {
      default: Header
    },
    {
      default: HomeList
    }
  ]) => {
    document.body.appendChild(Header())
    document.body.innerHTML += HomeList(3)
  })

Promise.all() 可执行多个异步

优化

使用最新版本

webpack 以及 nodejs最新版本

内置优化

将loader应用于最少数量的必要模块

解析必要的 提高打包速度

代码语言:javascript
复制
{
  test: /\.js$/,
  include: 'xxxxxx',
  loader: 'xxx'
}
能不用loader和plugin就不用 引导
解析

减少 resolve,modules,resolve.extensions,resolve.mainFiles,resolve.descriptionFiles中的条目数量

来减少系统文件调用次数

如果 不使用 symlinks 设置resolve.symlinks: false

如果自定义resolve plugin规则 并且没有指定 context,可以设置resolve.cacheWithContext:false

小即快

使用更少或者更小的library

在多页面应用使用splitChunksPlugin 并且开启async

移除未引用代码

只编译当前正在开发的代码

持久化缓存

在webpack配置中使用cache选项 使用package.json中的 "postinstall" 清除缓存目录

将cache类型设置为内存或者文件系统 memory 选项很简单 它告诉webpack在内存中存储缓存

cache: {

代码语言:txt
复制
type: 'memory'

}

自定义plugin/loader

对它们概要分析 以免在此处引入性能问题

权衡progress plugin的利弊

通用构建优化 dll

把包生成dll
代码语言:javascript
复制
const path = require('path')
const webpack = require('webpack')

module.exports = {
  mode: 'production',
  entry: {
    jquery: ['jquery']
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'dll'),
    library: '[name]_[hash]'
  },
  plugins: [
    new webpack.DllPlugin({
      name: '[name]_[hash]',
      path: path.resolve(__dirname, 'dll/manifest.json')
    })
  ]
}
引入
代码语言:javascript
复制
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
const path = require('path')

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  plugins: [
    new HtmlWebpackPlugin(),
    new webpack.DllReferencePlugin({
      manifest: path.resolve(__dirname, './dll/manifest.json')
    })
  ]
}

此时并不能使用

额外配置
代码语言:javascript
复制
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
const path = require('path')
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin')

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  plugins: [
    new HtmlWebpackPlugin(),
    new webpack.DllReferencePlugin({
      manifest: path.resolve(__dirname, './dll/manifest.json')
    })
    ,
    new AddAssetHtmlPlugin({
      filePath: path.resolve(__dirname, './dll/jquery.js'),
      publicPath: './'
    })
  ]
}

worker pool

注意 多个loader 从下到上运行

使用 thread-loader

用于非常耗时的loader

因为worker也会消耗资源

代码语言:javascript
复制
// const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  mode: 'development',
  entry: './src/index.js',

  module: {
    rules:[
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options:{
              presets: ['@babel/preset-env']
            }
          },
          {
            loader: 'thread-loader',
            options: {
              workers: 2
            }
          }
        ]
      }
    ]
  }


}

开发环境提升构建性能

使用webpack的 watch mode

监听过多导致的cpu负载

可用watchOptions.poll来增加轮询的时间间隔

在内存中编译

webpack-dev-server

webpack-hot-middleware

webpack-dev-middleware

stats.toJson加速
devtool

eval性能最好 但无法转译

cheap-source-map 稍差的map 但性能不错

eval-source-map 增量编译

多数情况为 eval-cheap-module-source-map

避免使用生产环境的工具

比如

TerserPlugin 压缩和混淆

fullhash/chunkhasn/contenthash

AggressiveSplittingPlugin

AggressiveMergingPlugin

ModuleConcatenationPlugin

最小化 entry chunk

optimization: { runtimeChunk: true }

避免额外优化步骤
代码语言:javascript
复制
optimization: { 
  removeAvailableModules: false,
  removeEmptyChunks: false,
  splitChunks: false
}
输出结果不要带路径信息
代码语言:javascript
复制
output: {
  pathinfo: false
}
nodejs版本

v8.9.10-v9.11.1存在性能回退

ts-loader

代码语言:javascript
复制
use: [
  {
    loader: 'ts-loader',
     options: {
      transpileOnly: true
    }
  }
]

生产环境提升构建性能

不启用 SourceMap

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • webpack5学习笔记
    • webpack笔记
      • 安装webpack
      • 配置入口文件(指令不如文件配置不可保存)
      • 配置出口
      • 文件配置
      • 自动引入资源
      • 搭建开发环境
      • 资源模块
      • loader使用
      • babel-loader
      • 分离代码
      • 缓存
      • 开发配置
      • source-map
      • webpack-server 配置
      • 模块热替换和热加载
      • 探索webpack原理
      • PostCSS和CSS模块 处理浏览器css兼容问题
      • WebWorks
      • 集成typescript
      • entry 配置
      • index.html模板配置
      • 多页面配置
      • Tree Shaking
      • 离线环境下运行
      • shimming 全局变量
      • 细颗粒度 shimming
      • 全局exports
      • polyfills 垫片
      • library
      • 发布为 npm-package
      • 模块联邦 多项目共享模块
      • 优化
      • 通用构建优化 dll
      • worker pool
      • 开发环境提升构建性能
      • 生产环境提升构建性能
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档