目录
第一篇:初始化项目
第二篇:代码规范
第三篇:Webpack 基本配置
第四篇:开发环境设置
第五篇:生产环境设置
第六篇:css、less、scss、图片支持
第七篇:IE11 兼容
第八篇:支持 React
第九篇:支持 Typescript>
第十篇:命令行工具
大家都知道木桶效应吧,一只木桶能盛多少水,并不取决于最长的那块木板,而是取决于最短的那块木板。
在前端开发中,IE 就是那块最短的木板,为了迁就 IE,我们不得不使用过时的 ES5 语法,很多新函数也因为 IE 的关系而无法使用。
之前的 less 篇章提到了转换的概念,那么有没有工具可以提供 IE 转换这一功能呢?
有的!
JS
转译
JS 转译工具名为 Babel,我们通过以下命令安装:
npm install babel-loader @babel/core @babel/preset-env -D
babel-loader 使用 babel 解析文件。
@babel/core 是 babel 的核心模块。
@babel/preset-env 转译 ES6+ 语法。
在根目录下新建.babelrc 文件,这个是 babel-loader 的配置文件,并输入:
{ "presets": [ [ "@babel/preset-env", { "modules": false } ] ] }
presets 是一些列插件集合
modules 防止 babel 将任何模块类型都转译成 CommonJS 类型
之后需要告诉 @babel/preset-env 我们需要转译浏览器版本。官方文档推荐使用browserlist,这也可以和之后的 css 配置保持一致。
打开我们的 package.json,添加如下字段:
{ //others "browserslist": [ ">0.2%", "not dead", "ie >= 11", "not op_mini all" ], //others }
对于上面配置不理解的同学可以在命令行中输入
npx browserslist
它会告诉你这么配置能支持哪些浏览器。
接下来打开我们的 webpack.common.js 文件,在 module.rules 增加以下代码:
module.exports = { //others module: { rules: [ { test: /\.js$/, loader: 'babel-loader', options: { cacheDirectory: true }, exclude: /node_modules/, }, //others ], }, }
匹配到 js 文件,就使用 babel-loader。
cacheDirectory babel-loader 在执行的时候,可能会产生一些运行期间重复的公共文件,造成代码体积大冗余,同时也会减慢编译效率,开启 cacheDirectory 后将这些公共文件缓存起来,下次编译就会加快很多。
exclude node_modules 目录不需要我们去编译,将对方排除以提升效率。
运行 build 发现箭头函数已经转译成 es5 语法了,这样就行了吗?no,我们还有一步重要的工作要做。
注入
熟悉 js 的同学都知道,Promise 或 .includes 这种新的 es 特性,是没办法转译到 es5 的。
比如在我们的 index.js 中加入一句代码
Promise.resolve().then(() => console.log(2))
你会发现 build 出来的 js 不会对 Promise 有任何处理,这也意味着IE 下必定会出错。
那么我们把这中新的语言特性的实现注入到打包后的文件中,不就行了吗?
这里借助 @babel/plugin-transform-runtime 这个插件,它和 @babel/polyfill 一样都能提供 ES 新 API 的垫片,都可实现按需加载,但前者不会污染原型链。
另外,Babel 对一些公共方法使用了非常小的辅助代码,比如 _extend。默认情况下会被添加到每一个需要它的文件中。
显然这会增加代码的冗余。
而 @babel/plugin-transform-runtime 会将所有的辅助函数都从 @babel/runtime-corejs3 导入,从而减少冗余。
npm install @babel/plugin-transform-runtime -D npm install @babel/runtime-corejs3 -S
注意: @babel/runtime-corejs3 的安装为生产依赖。
.babelrc 文件中输入:
{ "presets": [ [ "@babel/preset-env", { "modules": false } ] ], "plugins": [ [ "@babel/plugin-transform-runtime", { "corejs": { "version": 3, "proposals": true }, "useESModules": true } ] ] }
proposals:使用 corejs3 时必须开启
useESModules:默认是 false 的,这里开启是为了防止 tree-shaking 失效。
再次 build 发现 Promise 已经被处理了,去 IE 上看看效果吧。
CSS
IE 的兼容问题不仅仅体现在 js 上,还有 css。
Postcss 一种对 css 编译的工具,类似 Babel 对 js 一样通过各种插件对 css 进行处理,在这里我们主要使用以下插件:
postcss-flexbugs-fixes :用于修复一些和 flex 布局相关的 bug。
postcss-preset-env :将最新的 CSS 语法转换为目标环境的浏览器能够理解的 CSS 语法。使用 autoprefixer 来自动添加浏览器头。
postcss-normalize :从 browserslist 中自动导入所需要的 normalize.css 内容。
npm install postcss-loader postcss postcss-flexbugs-fixes postcss-preset-env postcss-normalize -D
用法和之前 css 篇的其他 loader 一样,我们需要在 css-loader 之前使用。
为此,抽取出来的公用函数 cssLoaders 需要做些调整。
修改 webpack.common.js
const cssLoaders = (preNumber) => [ isDev ? 'style-loader' : MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { sourceMap: isDev, importLoaders: preNumber + 1, }, }, { loader: 'postcss-loader', options: { postcssOptions: { plugins: [ 'postcss-flexbugs-fixes', [ 'postcss-preset-env', { autoprefixer: { grid: true, flexbox: 'no-2009', }, }, ], 'postcss-normalize', ], }, sourceMap: isDev, }, }, ]
importLoaders需要+1操作,另外browserslist 的设置之前 js 篇有设置过,因此不需要重复设置。
来试试效果吧,
修改 app.css
@import 'normalize.css/opinionated.css'; .app { flex: 1; font-family: system-ui; text-align: center; background-color: #12345678; } ::placeholder { color: gray; }
别忘了在 index.js 中 import 一下。
import './app.css' kintone.events.on('app.record.index.show', (event) => { const root = kintone.app.getHeaderSpaceElement() root.innerHTML = '<div class="app"><h1>hello kintone!</h1></div>' return event })
为了更好的看效果,让我们先注释掉 webpack.prod.js 中的 PurgeCSSPlugin 和 CssMinimizerPlugin 配置。
build 一下,去看看生成的 css 文件吧。
热更新的bug
相信大家都还记得,我在开发环境配置中曾经提过一次,3系的 web-dev-server 搭配 webpack5 及 browserlist 会导致LiveReloading 失效。
关于Babel,可以考虑把browserlist的内容复制到 @babel/preset-env 的 targtes 属性下。
但对于 postcss-normalize 却没有什么好办法。
这里推荐的解决案是在 webpack.common.js 中添加一行:
module.exports = { target: isDev ? 'web' : 'browserslist', //others }
缺点是无法用 IE 来调试,不过没什么人会用IE来调试吧。