前端最常用的打包工具webpack(三)-兼容性处理
这是重新学习webpack的第三篇文章,之前我也写过一篇关于webpack的文章。问题是过去快半年了,~~我已经将webpack忘得差不多,~~回头一看那篇文章完全是一头雾水,也没有办法,那个时候我才刚刚开始写前端方面的博客,对于知识梳理、文字表达都有一些欠缺,啪啪啪一下扔出来几千字,全是重点,没有任何过渡性的语言,看个一会就没什么兴趣。
综上所述,本次决定给webpack写一个比较详细的系列文章,目的是如果我半年后又忘记了webpack的具体内容,再来翻阅文章,不会像这次一样一头雾水。
前景提要
在之前的那篇文章中,我学到了如何将css、js、scss、html通过webpack进行打包,而本篇文章,就着重讲解如何处理js、css的兼容性,以及如何将项目运行在webpack内置的服务器上。
1. 兼容性
1.1 css兼容性
css因为每个浏览器实现的方式不同,而且不同的浏览器还有各自的私有属性:
常用的前缀有:
- -moz代表firefox浏览器私有属性。
- -ms代表IE浏览器私有属性。
- -webkit代表chrome、safari私有属性。
- -o代表opera私有属性。
例如transform:rotate(-3deg)
这个css属性,兼容性写法就应该是:
-webkit-transform:rotate(-3deg); /* 为Chrome/Safari */-moz-transform:rotate(-3deg); /* 为Firefox */-ms-transform:rotate(-3deg); /* 为IE */-o-transform:rotate(-3deg); /* 为Opera */transform:rotate(-3deg);
试想一下,如果每一条CSS3的语句都要写成这样,那几乎不用玩了,不光你要一条条的查找该CSS属性是否存在兼容性问题,你还必须写上这些私有属性语句。
虽然现在有些网页能够帮助你将CSS语句进行转换,但是一个页面中可能有非常多的.css
文件,你要一个一个的去转换肯定是不现实的。
这个时候webpack通过插件,可以自动帮你添加这些兼容性语句,你只需要专心写css相关的样式就可以了。
1.2 js兼容性
因为有些浏览器比如IE浏览器不识别ES5之后的语法,而ES6里面有太多的便利的写法,不仅引入了箭头函数解决了历史遗留的this指针问题,还引入了class、promise这些十分方便的新特性,你总不可能不用ES6的语法再回去写ES5的语法吧?
而webpack有插件可以直接将ES6后的语法转换为ES5的语法,你只需要进行配置一下,你就可以放心的书写ES6的语法,而不用担心兼容性问题,所有的兼容性问题插件会帮助你解决。
相信看到这里,你一定对本篇文章所要讲述的内容有一定的了解,那么我们就开始吧!
2. CSS
2.1 提取CSS到单独文件
之前我们一直将CSS放在.js
中,但是这样无疑会增大.js
文件的体积,而且有些浏览器对js文件的解析速度还没有css文件的解析速度快,所以我们需要把样式文件单独提取出来。
需要的插件mini-css-extract-plugin。
npm install mini-css-extract-plugin --save-dev
配置也很简单:
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// 在css loader中用MiniCssExtractPlugin.loader替代style-loader{ // 用正则表达式匹配文件类型,下面就是匹配以.css结尾的文件,并且将它们使用下面的loader解析。 test: /\.css$/, use: [ MiniCssExtractPlugin.loader, // 将css文件编程CommonJs模块加载到js中,里面内容是样式字符串 "css-loader", { loader: "postcss-loader", options: { postcssOptions: { // 浏览器兼容性处理 plugins: ["postcss-preset-env"], }, }, }, ],},
// 在plugins中引入插件new MiniCssExtractPlugin(),
这样我们打包项目中的样式文件就会单独的放在一个.css
文件中。当然我们也可以通过配置插件的filename
属性命名打包后的.css
文件。
new MiniCssExtractPlugin({ // 对输出的样式文件重命名 filename: "css/style.css",}),
2.2 兼容性处理
这里需要使用到PostCSS。
PostCSS是一个用来处理项目中CSS文件的工具,它具有非常多的功能,同时拥有大量插件,可以实现处理CSS兼容性问题,处理CSS重复代码问题等等一系列的问题。
因为我对PostCSS也没有深入研究,所以这里只是讲解一下它如何处理CSS各个厂商的私有属性。
首先我们需要引入两个包:
npm install postcss-loader postcss-preset-env --save-dev
在package.json
文件中添加下面的代码,当然也可以单独提取出来做一个文件,文件名要命名为:.browserslistrc
。
下面代表适配浏览器的版本,关于更多配置可以到browserslist。进行查看,而我这里直接拿了vue项目默认的兼容性配置。
"browserslist": [ "> 1%", "last 2 versions", "not dead"]
然后修改webpack.config.js中的配置。
// 在loader中配置{ // 用正则表达式匹配文件类型,下面就是匹配以.css结尾的文件,并且将它们使用下面的loader解析。 test: /\.css$/, use: [ MiniCssExtractPlugin.loader, // 将css文件编程CommonJs模块加载到js中,里面内容是样式字符串 "css-loader", { loader: "postcss-loader", options: { postcssOptions: { // 浏览器兼容性处理 plugins: ["postcss-preset-env"], }, }, }, ],},
到这里再通过webpack打包:
打包前:
* { padding: 0; margin: 0; box-sizing: border-box; display: flex; backface-visibility: hidden;}
打包后:
* { padding: 0; margin: 0; box-sizing: border-box; display: flex; -webkit-backface-visibility: hidden; backface-visibility: hidden;}
可以看到PostCSS自动为我们做了兼容性处理。
2.3 压缩CSS
可以看到我们上面的CSS虽然经过了打包,但是没有进行压缩,所谓的压缩就是去掉代码的格式,让代码紧挨在一起,从而减小代码的体积。
npm install css-minimizer-webpack-plugin --save-dev
使用也非常简单:
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
// 引入插件new CssMinimizerPlugin(),
重新进行打包,会发现css文件已经被压缩:
*{padding:0;margin:0;box-sizing:border-box;display:flex;-webkit-backface-visibility:hidden;backface-visibility:hidden}
3. js
3.1 Eslint
代码风格检测,因为JavaScript语言为脚本语言,所以写法非常的自由,在团队协作开发时,可能你用的是双引号,我用的是单引号,你句尾加;
号,而我句尾不加。
这些场景非常常见,有时候会因为代码样式问题造成合代码时产生大量冲突,Eslint的出现就是为了解决团队代码风格不一致的问题,它可以通过配置文件让你强制使用双引号或者单引号、句尾加;
或不加;
。让一个项目的代码运用一种风格进行编写。
同时Eslint还会检测出部分代码中可能暗藏BUG的语句。
引入Eslint的目的是为了统一代码风格,提高团队效率,而且现在在vscode上面也有Eslint插件(WebStorm上自带Eslint插件)可以在保存的时候根据规则进行自动修复。而我其实对于Eslint是非常喜爱的。
引入:
npm install eslint-webpack-plugin eslint --save-dev
配置:
const ESLintPlugin = require("eslint-webpack-plugin");
new ESLintPlugin({ // 自动修复代码 fix: true,}),
这里配置就完成了,你可以直接在项目中输入命令:
eslint --init
生成配置文件,它可以选择3个大公司的Eslint规则,分别是:
- Airbnb: https://github.com/airbnb/javascript
- Standard: https://github.com/standard/standard
- Google: https://github.com/google/eslint-config-google
在过去Airbnb用的是非常多的,但是我其实更喜欢使用prettier,因为prettier更接近我平时写代码的风格,而且最近使用prettier的越来越多。
prettier使用
下载:
npm install eslint-config-prettier eslint-plugin-prettier prettier --save -dev
在项目根目录中创建.eslintrc.js
文件,写入下面的代码。
module.exports = { env: { browser: true, es2021: true, }, extends: ["prettier", "plugin:prettier/recommended"], parserOptions: { ecmaVersion: 12, sourceType: "module", }, rules: {},};
3.2 兼容性处理
正如上面所说,有些浏览器不认识ES6的语法,所以我们需要对这些代码做一些兼容性处理。
如果我们有下面的js代码:
import "./src/style.css";
const promise = new Promise((resolve) => { setTimeout(() => { resolve(2); });});
promise.then((req) => { console.log(req);});
可以看到我们这里不光用了ES6的const
还用了Promise
,最终的打包结果是:
!function(){"use strict";new Promise((e=>{setTimeout((()=>{e(2)}))})).then((e=>{console.log(e)}))}();
而Promise
没有经过兼容性处理,这个时候我们就需要引入下面的包:
npm install -D babel-loader @babel/core @babel/preset-env core-js
配置:
{ test: /\.js$/, exclude: /node_modules/, use: [ { loader: "babel-loader", options: { // 预设:指示babel做怎么样的兼容性处理。 presets: [ [ "@babel/preset-env", { corejs: { version: 3, }, // 按需加载 useBuiltIns: "usage", // 需要适配的最低版本 targets: { chrome: "60", firefox: "60", ie: "9", safari: "10", edge: "17", }, }, ], ], }, }, ],},
再进行一次打包,看一下最后我们打包的js文件,发现多了很多代码,这是因为将Promise
转化成了ES5的形式进行实现。
4. devSever
在之前的项目中,我们的目录结构最重要的两个文件夹:
- build:打包后项目的代码。
- src:项目的源代码。
我们最好将项目的源代码放在src
中进行统一管理,但是我们运行的项目是build
目录中最终打包后的项目,如果我们源代码发生了改变,我们就必须要手动执行一次打包命令进行重新打包,不然build
目录下依然是上次打包后的结果。
为了实现项目热更新,我们需要用到webpack-dev-server。
它实现了项目的热更新,需要注意的是,它的操作是在内存中进行完成,并不会输出打包文件,首先进行下载:
npm install webpack-dev-server --save-dev
在webpack.config.js
中增加配置:
devServer: { // 项目构建后的路径 contentBase: resolve(__dirname, "build"), // 启动gzip压缩 compress: true, // 端口号 port: 3000, // 自动打开浏览器 open: true,},
- contentBase:项目构建后的路径。
- compress:gzip压缩。
- port:端口号。
- open:打开浏览器,默认为false。
配置完毕后输后在终端中输入:
webpack serve
等待一会,发现会打开一个新窗口。
新窗口中就可以看到之前的项目。
这个时候只要代码进行了改动,devSever就会自动帮我们再进行打包、刷新浏览器等操作。
5. 最后
到这里为止,webpack的基础内容几乎已经全部学习完毕,经过本次的学习,我学到了如何处理CSS和JS的兼容性问题,同时我也学到了如何通过webpack打开一个服务器。
但是webpack的学习之旅还没有结束,我们只是会了基础的webpack配置,还有关于项目优化的配置我们还没有进行学习,比如如何优化打包速度,如何加快项目启动速度,如何加快热更新速度,这些都影响着我们实际开发中的效率。