今天继续填webpack坑啦。继上次讲了webpack5编译和处理css文件后,今天聊一聊webpack5是如何处理js文件的。
目标
- 编译ES6
- 引入eslint
- 压缩js文件
- 引入全局变量
知识点脑图
项目中用到的代码
编译ES6
编译ES6语法是通过babel实现的。
-
安装babel
yarn add babel-loader @babel/core @babel/preset-env -D-
@babel/core 是使用Babel进行转码的核心npm包,使用的babel-cli,babel-node都依赖这个包
-
@babel/preset-env 是babel预制套件,包含各种可能用到的转译工具
-
-
在webpack.config.js的 module,rules中加入babel配置。注意加includes,仅处理src文件夹中的js文件
{
test: /\.js$/, //匹配js文件
use: ['babel-loader'],
include: path.resolve(__dirname, 'src')
}
- 新增一个.babelrc文件,配置babel
{
"presets": [
"@babel/preset-env"
],
"plugins": []
}
- 用了以上配置后,发现还是不能用async await 。网上找了以下,需要安装
@babel/plugin-transform-runtime才可以 - 安装
@babel/plugin-transform-runtime,yarn add @babel/runtime @babel/plugin-transform-runtime - 修改
.babelrc文件,配置transform-runtime。此时async await就可以使用了。
{
"presets": [
"@babel/preset-env"
],
"plugins": [
"@babel/plugin-transform-runtime"
]
}
(网上说 @babel/runtime 是运行环境中所需要的依赖包,要安装在dependencies里;而 @babel/plugin-transform-runtime 是开发依赖,只用安装在 devDependencies里,试了下,并不是网上说的这样,都安装在devDependencies里也是可以的 )
添加eslint-loader 格式化代码
- 安装 eslint 和 eslint-loader
yarn add eslint eslint-loader -D - 在 webpack.config.js 中配置 babel-loader
{
test: /\.js$/, //匹配js文件
use: ['babel-loader',
{
loader: 'eslint-loader',
options: {
enforce: 'pre' // 前置loader,webpack会优先处理
}
}
],
include: path.resolve(__dirname, 'src')
},
- 在根目录下新增 .eslintrc.json。文件来源于官网demo下载的文件 cn.eslint.org/demo/
- 做完以上步骤后,会发现,项目报错了,3个问题
//问题1
module没有定义
//问题2
const是保留字
// 问题3
ESLint Parsing error: Unexpected token
- 问题1和2的解决方法是,配置eslint,使其支持es6和node语法。问题3是引入 babel-eslint。先安装 babel-eslint, 然后修改 .eslintrc.json
// 安装babel-eslint
yarn add babel-eslint -D
// 修改 .babelrc.json
{
... // 其他配置项
"env": {
"es6": true,
"node": true
},
"parser": "babel-eslint"
}
- 重启服务 npm run dev, eslint 就配置好了
压缩js文件
- terser-webpack-plugin 是用来压缩js的plugin
- 配置此插件
const TerserWebpackPlugin = require('terser-webpack-plugin')
optimization: {
minimizer: [
new OptimizeCssAssetsWebpackPlugin(),
new TerserWebpackPlugin()
]
}
- 重新打包 npm run build。可以对比压缩之前和压缩之后的js文件,明显变小。
引入全局变量
有些插件是很多组件都需要使用的,例如jquery,引入一个全局属性$指向jquery对象,对我们非常方便且必要。引入全局对象有两种方法,1.ProvidePlugin 2.expose-loader。下面就分别讲一下,如何用这两种方式注入全局变量。
- 全局注册jQuery
- 全局安装jQuery,
yarn add jquery - 使用webpack模块提供的ProvidePlugin插件,引入全局属性
$,指向jquery对象
// 引入 webpack 模块
const Webpack = require('webpack')
// 在webpack.config.js的plugins中加入下面代码
new Webpack.ProvidePlugin({
$: 'jquery' // 将jQuery加到全局变量中
})
- 重新启动服务,会发现有个报错
'$' is not defined no-undef - 这个报错是eslint报出来的。找了下原因,是因为全局变量jquery或者$需要先声明下。修改 .eslintrc.json。然后重启服务。(修改了.eslintrc.json后,需要手动重启才能生效)
// 亲测下面两种方式都有效
// 在env中添加jquery: true
"env": {
"es6": true,
"node": true,
"jquery": true
},
// 或者添加 和 env 平级的 globals 属性
"globals": {
"$": true
},
- 以上讲的是通过
webpack.ProvidePlugin来注入全局变量,还可以通过expose-loader添加全局变量。在开始演示之前,先解决index.js中如何兼容import 和 require的问题。还是修改下 .eslintrc.json,然后重启服务
{
... // 其他属性
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module",
... // 其他属性
},
... // 其他属性
}
下面以dayjs为例来说明,如何使用expose-loader 来引入全局变量,安装dayjs yarn add day.js,先说下内联方式的用法。
expose-loader是内联loader,既可以用内联的方式使用,也可以用webpack.config.js中配置的方式使用。先说下内联使用
1. 在info.js文件中写上以下代码。意思是将 `$day` 添加到全局对象中,其名称为 $day
import $day from "expose-loader?exposes=$day!dayjs"
2. 在需要使用day.js的文件中,直接使用 $day 即可
const time = $day().format('YYYY-MM-DD')
console.log(time)
- 做好以上配置后,重启服务,会发现报错
'$day is not defined no-undef。 eslint报错了,需要在eslint中再加个配置,声名以下全局属性$day
"globals": {
"$day": true
},
expose-loader除了用在组件中,还可用在webpack.config.js中。使用方法可以参考官网 webpack.docschina.org/loaders/exp…,具体实现分为两步,1. webpack中配置 expose-loader 2. 在顶层的js中配置import $day from "dayjs"
// step1:在webpack中配置 expose-loader
{
// require.resolve 调用是一个 Node.js 函数,用于给出模块的绝对路径
test: require.resolve('dayjs'),
loader: 'expose-loader',
options: {
exposes: ['$day']
}
},
// step2: 在第一个执行的js文件里引入 dayjs
import $day from "dayjs"
结语
今天关于webpack5对js的处理就介绍到这里了,后面会继续更新webpack5编译和打包图片文件