webpack5的入门笔记
1.入口和出口的配置文件webpack.config.js
//1.入口文件和出口文件跟webpack4一样
const path = require('path')
module.exports = {
mode: 'development',//生成环境是production
//入口文件
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js'
},
2.loader的使用
css-loader
css-loader
的使用要配合style-loader
在项目中的配置文件webpack.config.js
来配置下载css-loader和style-loader
//在 module中配置loader module: { rules: [ { test: /\.css$/i, use: ["style-loader", "css-loader"], //loader是从右向左解析的 }, ], },
less-loader
你需要先安装
less
和less-loader
npm install less less-loader --save-dev
配置
module: { rules: [ { test: /\.css$/i, use: ["style-loader", "css-loader"], }, { test: /\.less$/i, use: ["style-loader", "css-loader", "less-loader"] } ] },
postcss-loader是一款使用插件去转换CSS的工具
要安装
postcss-loader
和postcss
npm install --save-dev postcss-loader postcss
安装一个
autoprefixer
自动补全插件npm i -D postcss-loader
配置 在
css-loader or less-loader or sass-loader之前添加postcss-loader
{ test: /\.css$/i, use: ["style-loader", "css-loader", "postcss-loader"], }, //或者是 { test: /\.css$/i, use: ["style-loader", "css-loader","less-loader" "postcss-loader"], }
需要一个postcss的配置文件
postcss.config.js
module.exports = { plugins: [ require('autoprefixer') ] }
webpack5中就不用autoprefixer要安装一个
postcss-preset-env
插件npm install postcss-preset-env
在postcss.config.js中配置插件
module.exports = { plugins: [require('postcss-preset-env')] }
在package.json中添加浏览器的版本控制
"browserslist": [ "last 1 version", "> 1%", //兼容的比例 "maintained node versions", "not dead" ]
如果一个样表中引入了另外一个样式表,则需要在加载的loader修改一个options参数
rules: [ { test: /\.css$/i, use: ["style-loader", { loader: "css-loader", options: { importLoaders: 2, esModule: true, }, }, "postcss-loader", "less-loader"], } ]
图片处理的loader
file-loader可以指定要复制和放置资源文件的位置
下载
npm install file-loader --save-dev
配置
module.exports = { module: { rules: [ { test: /\.(png|jpg|gif)$/, use: [ { loader: 'file-loader', options: { name: '[name].[ext]' }, }, ], }, ], }, };
url-loader
url-loader 允许你有条件地将文件转换为内联的 base-64 URL (当文件小于给定的阈值)
npm install url-loader --save-dev
配置
rules: [ { test: /\.(png|jpg|gif)$/i, use: [ { loader: 'url-loader', options: { limit: 8192 //最大阈值 } } ] } ]
在webpack5中使用资源模块(asset module)是一种模块类型,它允许使用资源文件(字体,图标等)而无需配置额外 loader。
资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader
asset/resource
发送一个单独的文件并导出 URL。之前通过使用file-loader
实现。asset/inline
导出一个资源的 data URI。之前通过使用url-loader
实现。asset/source
导出资源的源代码。之前通过使用raw-loader
实现。
配置图片资源加载对应的是
file-loader
{ test: /\.(png|svg|jpg|jpeg|gif)$/i, type: 'asset/resource', generator: { filename: 'image/[name]-[hash:4].[ext][query]' } },
将图片处理为data URl的形式使用
type:asset/inline
对应的是url-loader
{ test: /\.(png|svg|jpg|jpeg|gif)$/i, type: 'asset/inline', },
将type设置为
type:asset
,webpack 将按照默认条件,自动地在resource
和inline
之间进行选择{ test: /\.(png|svg|jpg|jpeg|gif)$/i, type: 'asset', generator: { filename: 'image/[name].[ext]' }, parser: { dataUrlCondition: { maxSize: 70 * 1024 } } },
加载字体图标
{ test: /\.(woff|woff2|eot|ttf|otf)$/i, type: 'asset/resource', generator: { filename: 'font/[name].[hash:3][ext]' } },
3.webpack 中插件的使用
clean-webpack-plugin
清除打包文件插件
```js
npm install --save-dev clean-webpack-plugin
```
1. 在webpack.config.js中引入和配置
```js
const CleanWebpackPlugin = require('clean-webpack-plugin');
plugins: [
new CleanWebpackPlugin()
]
```
html-webpack-plugin
插件的使用下载安装
npm install --save-dev html-webpack-plugin
导入插件和配置
const HtmlWebpackPlugin = require('html-webpack-plugin'); plugins: [ new HtmlWebpackPlugin( { title: 'webpack的插件使用',//配置的title template: './public/index.html',//使用的模板 } ), new CleanWebpackPlugin() ]
DefinePlugin
允许在 编译时 将你代码中的变量替换为其他值或表达式这个插件是webpack的内置的一个插件
使用方法
//导入 const { DefinePlugin } = require('webpack') //配置 new DefinePlugin({ //常量的配置使用的是键值对的形式 BASE_URL: "'./'" //.icon的路径 })
4.babel-loader的使用
babel-loader是将ES6代码转为ES6
使用方法
安装相关的loader
npm install -D babel-loader @babel/core @babel/preset-env
先关的配置
{ test: /\.js$/, exclude: /(node_modules|bower_components)/, //排除node_modules这么目录 use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } }
也可以单独抽离出一个babel.config.js的配置文件
//babel.config.js配置文件 module.exports = { presets: ['@babel/preset-env'] } //在webpack.config.js中可以是配置loader了 { test: /\.js$/, exclude: /(node_modules|bower_components)/, use: ['babel-loader'] }
5.polyfill的使用
polyfill是babel-loaer的补充,兼容更高级的语法,在webpack中polyfill是单独的包,如果要使用则要按需加载
在bable7.4.0以上建议引入"core-js/stable"和
regenerator-runtime/runtime
.安装先关依赖
npm install core-js regenerator-runtime
在babel.config.js中配置
module.exports = { presets: [["@babel/preset-env", { useBuiltIns: 'usage', //'usage'根据用户当前源代码使用的新语法来填充,'entry'根据当前筛选的浏览器来填充;默认的值的'fasle' corejs: 3 }]] }
6.CopyWebpackPlugin插件的使用
安装插件
npm install copy-webpack-plugin --save-dev
在webpack.config.js中的配置
new CopyPlugin({ patterns: [ { from: 'public',//拷贝的目录 globOptions: {//排除不需要拷贝的内容 ignore: ['**/index.html'] } } ] })
7.webpack-dev-server
webpack-dev-server是提供一个简易的web服务,修改代码可以实时加载
下载
npm install --save-dev webpack-dev-server
配置
module.exports = { devServer: { static: './dist', //服气器查找的文件位置 }, }
在package.json中添加配置
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack-dev-server --open", // 使用npm run start 启动服务 },
8.模块热替换HRM
作用是在运行是更新各种模块,无需进行完全刷新
使用方法
在webpack.config.js中引入插件
具体使用查看
在模块是使用
if (module.hot) { module.hot.accept('./js/print.js', function () { console.log('加载的模块print'); printMe() }) }
9.devServer中的代理设置
webpack中的devServer默认就是开启了一个服务
devServer: { port: 8080, // 源地址端口,自行修改 proxy: { '/': { target: 'http://localhost:3000', // 跨域目标主机,自行修改 ws: true, // 代理 websockets changeOrigin: true, pathRewrite: { '^/api': '' // 重写地址 } }, } }
10.source map的使用
- 为了更容易地追踪 error 和 warning,JavaScript 提供了
source maps
功能,可以将编译后的代码映射回原始源代码 - Devtool此选项控制是否生成,以及如何生成 source map。
- 配置:
devtool: 'source-map',
devtool的默认值是eval
- devtool对应的值以及作用
- 默认值是
eval
生成的代码是没有映射 - 值为
source-map
生成.map的文件,与原代码生成一个映射关系,可以方便的查找代码的报错位置 - 值为
eval-source-map
打包的代码没有一个.map的映射文件,但是代码可以中可以查找到报错位置 - 值为
inline-source-map
时打包代码没有一个.map的映射文件 - 值为
cheap-source-map
,报错只提供行信息,不提供列信息 - 值为
cheap-module-source-map
报错信息精确到行和列 - 值为
hidden-source-map
,隐藏了.map文件 - 在是实际开发中常用的是
source-map
和cheap-nodeule-source-map
- 默认值是
11.webpack对typescript打包的使用
下载先关依赖
npm install --save-dev typescript ts-loader
在项目的根目录中配置
tsconfig.json
的配置文件{ "compilerOptions": { "outDir": "./dist/", "noImplicitAny": true, "module": "es6", "target": "es5", "allowJs": true, "moduleResolution": "node" } }
在webpack.config.js中配置loader
rules: [ { test: /\.ts?$/, use: 'ts-loader', exclude: /node_modules/, }, ],
但是
ts-loader
只是把ts转为js,但是对于想Promise这类的内容没有填充转换,所以在这要使用babe
中对ts的预设@babel/preset-typescript
下载
@babel/preset-typescript
npm install --save-dev @babel/preset-typescript
在
.babel.config.js
配置预设module.exports = { presets: [ ["@babel/preset-env", { useBuiltIns: 'usage', corejs: 3 } ], ["@babel/preset-typescript"] //ts的预设配置 ] }
这时就不用
ts-loader
了,要使用babel-loader
{ test: /\.ts?$/, use: ['babel-loader'], exclude: /node_modules/, },
使用
ts-loader
可以对ts语法进行校验,babel-loader
不能对ts语法校验,因此在需要对ts语法做校验又要使用babel-loadr
,可以在webpack.json中配置一个命令"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "npm run tsc && webpack", //打包前先校验语法 "start": "webpack serve", "tsc":"tsc --noEmit" //校验ts语法 },
12.区分打包环境
环境的区分
生成环境和开发环境的区分,在webpack4+中通过
mode
的值来区分,production
生成环境,development
是开发环境在
package.json
中的可以通过配置参数来获取当前的环境变量"scripts": { "build": "npm run ck && webpack", "build1":"webpack --config webpack.base.js --env production", //--env production环境参数 "build2":"webpack --config webpack.base.js --env development",//--env production环境参数 "start": "webpack serve", "ck": "tsc" },
这是在webpack.base.js通过参数的形式获取
module.exports = (env) => { console.log(env, '<---------------') } //打印的参数是:{ WEBPACK_BUNDLE: true, WEBPACK_BUILD: true, development: true } <--------------- //这就可以获取传递的参数
webpack.config.js的拆分
拆分一个开发环境,生成环境和一个公共的配置文件
//生产环境的webpack module.exports = { mode: 'production',//'development'||'production' devtool: '', //此选项控制是否生成,以及如何生成 source map。 }
//开发环境的webpack配置 module.exports = { mode: 'development',//'development'||'production' devtool: 'cheap-module-source-map', //此选项控制是否生成,以及如何生成 source map。 target: "web", devServer: { static: './dist', hot: true, compress: true }, }
//webpack代码抽离的公共部分 const path = require('path') const { CleanWebpackPlugin } = require('clean-webpack-plugin') const HtmlWebpackPlugin = require('html-webpack-plugin') const { DefinePlugin, HotModuleReplacementPlugin } = require('webpack') const CopyPlugin = require("copy-webpack-plugin"); const { merge } = require('webpack-merge'); //用于代码的合并 //导入pro.js 和 dev.js const proConfig = require('./webpack.pro.js'); const devConfig = require('./webpack.dev.js') //抽离的公共的配置 const baseConfig = { entry: './src/main.ts', output: { path: path.resolve(__dirname, 'dist'), filename: 'main.js' }, resolve: { extensions: ['.js', '.json', '.ts', '.vue'], alias: { "@": path.resolve(__dirname, 'src') } }, module: { rules: [ { test: /\.css$/i, use: ["style-loader", "css-loader", "postcss-loader"], }, { test: /\.(png|svg|jpg|jpeg|gif)$/i, type: 'asset', generator: { filename: 'image/[name].[ext]' }, parser: { dataUrlCondition: { maxSize: 40 * 1024 } } }, { test: /\.(woff|woff2|eot|ttf|otf)$/i, type: 'asset/resource', generator: { filename: 'font/[name].[hash:3][ext]' } }, { test: /\.js$/, exclude: /(node_modules|bower_components)/, use: ['babel-loader'] }, { test: /\.ts$/, use: ['babel-loader'], exclude: /node_modules/, }, ], }, plugins: [ new HtmlWebpackPlugin( { title: 'webpack的插件使用', template: './public/index.html', } ), new CleanWebpackPlugin(), new DefinePlugin({ //常量的配置使用的是键值对的形式 BASE_URL: "'./'" }), new CopyPlugin({ patterns: [ { from: 'public', globOptions: { ignore: ['**/index.html'] } } ] }), //热更新插件 new HotModuleReplacementPlugin() ], } module.exports = (env) => { //定义一个变量接收参数 const isProduction = env.production const comConfig = isProduction ? merge(proConfig, baseConfig) : merge(devConfig, baseConfig) return comConfig //根据不同的环境导出不同的模式 }
13.代码的拆分
方式1,多入口的方式
//使用多入口的方式打包 entry: { index: './src/main.js', other: './src/other.js' }, //输入的文件的文件名使用`[name].js` output: { //出口文件,是绝对路径,要是用node的path模块 path: path.resolve(__dirname, './dist/'), filename: '[name].js', },
如果代码依赖依赖第三方库代码的打包方式
entry: { index: './src/index.js', index2: { import: './src/index2.js', dependOn: 'jquery' }, jquery: "jquery" }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].js' },
若干代码依赖多个第三方库的打包方式
const baseConfig = { entry: { index: './src/index.js', index2: { import: './src/index2.js', dependOn: 'shared' }, shared: ['jquery', 'lodash'] }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].js' }, }
可以使用
splitChunks
插件进行拆包optimization: { minimizer: [ new TerserPlugin({ extractComments: false }), ], splitChunks: { runtimeChunk:true,//修改运行的代码,都会生成不同的的哈希值,没有修改的就不变 chunks: 'initial', //chunks的值有`all`,'async' minSize: 20000, //模块在压缩前的大小最小值,单位是字节 minChunks: 1, //表示要被提取的模块最小被引用次数 cacheGroups: { // vendors: { name: `chunk-vendors`, test: /[\\/]node_modules[\\/]/, priority: -10, //优先级 chunks: 'initial' }, common: { name: `chunk-common`, minChunks: 2, priority: -20,//优先级 chunks: 'initial', reuseExistingChunk: true } } } },
使用import动态导入包