之前封装一些通用
这个简直就是必备啊!虽然现在大部分浏览器对ES6+的支持已经很好了,但是永远不能保证用户的浏览器……
下面就切入正题,先弄一个项目作为本章节的测试,目录结构如下:
// 下面是 src/index.js 文件的内容 document.addEventListener("DOMContentLoaded", () => { // 模板字符串``相关 console.log(`模板字符串-反引号=>现在时间:${new Date()}`); // 解构赋值相关 let { log } = console; const PI = 3.14; log("解构console之log方法,之后输入常量π的近似值:" + PI); let contextInfo = { readonly: false, userInfo: { name: "ddz001", pwd: "", tokenId: "666" }, p1: "", fn1() { console.log("contextInfo.fn1"); } }; let { readonly: isReadOnly, p1 } = contextInfo; console.log("对象解构赋值之是否只读:" + isReadOnly); console.log("对象解构赋值之p1:" + p1); let [arrIndex0 = 10, arrIndex1, arrIndex2, arrIndex3 = 4] = [0, [1, 2], 3]; console.log("数值解构赋值之第一个:" + arrIndex0); console.log("数值解构赋值之第二个:" + arrIndex1); console.log("数值解构赋值之第三个:" + arrIndex2); console.log("数值解构赋值之第四个:" + arrIndex3); // 类(Class)相关 class Person { constructor(name) { this.name = name; this.gender = ""; this.birthday = ""; this.idCard = ""; } sayName() { return this.name; } } let person1 = new Person("ddz001"); console.log(person1); // async、await 关键字相关 async function promiseFn1() { return "async、await相关:该方法没有返回Promise,而是在方法前添加async"; } let retPromiseFn1 = promiseFn1(); console.log("async、await相关:" + Object.prototype.toString.call(retPromiseFn1)); async function promiseFn2() { // let isTrue = await Promise.resolve(true); let isTrue = await true; let retPromiseFn1 = await promiseFn1(); console.log("async、await相关:" + isTrue); console.log("async、await相关:" + retPromiseFn1); } promiseFn2(); //**************************************************************************************************************/ console.log("数组实例方法includes:" + [1, 2, 3].includes("1")); console.log("数组实例方法includes:" + [1, 2, 3].includes(3)); let arrFromStr = Array.from("利用Array.from将字符串转成数组!"); console.log(arrFromStr); let set1 = new Set([1, 6, 6, 6, 8, 8, 8, 9]); console.log(set1); Promise.resolve(999).then(x => { console.log("Promise返回值:" + x); }); });
// 下面是 package.json 文件的内容(还没有添加依赖) { "name": "xxx", "version": "1.0.0", "main": "index.js", "license": "MIT", "scripts": { "c": "rollup -c", "cw": "rollup -cw" } }
各种尝试主要是针对“打包依赖”和rollup.config.js来说的。第一次尝试最简单:
# 你可以用下面的命令安装 yarn add @babel/core @rollup/plugin-babel rollup -D
// 下面是 rollup.config.js 文件的内容 import { babel } from '@rollup/plugin-babel'; export default { input: './src/index.js', output: { file: 'dist/index.js', format: 'iife' }, plugins: [ babel() ] };
babelHelpers: 'bundled' option was used by default. It is recommended to configure this option explicitly, read more here: https://github.com/rollup/plugins/tree/master/packages/babel#babelhelpers
说明:代码没有变化,只是外边添加一个立即执行函数
第二次尝试,依赖慢慢添加。
# 你可以用下面的命令安装 yarn add @babel/core @babel/preset-env @rollup/plugin-babel rollup -D
// 下面是 rollup.config.js 文件的内容 import { babel } from '@rollup/plugin-babel'; export default { input: './src/index.js', output: { file: 'dist/index.js', format: 'iife' }, plugins: [ babel({ presets: ['@babel/preset-env'] }) ] };
说明:上面的配置只会转换一些语法,例如:let、const、class、数组或者对象的解构赋值等,async和await也会转换(转换之后用到了Promise);像新增的Array.from、Set、Promise等不会转换。
在浏览器中运行的时候报错了,还是Chrome,并且是最新版的,什么鬼……
Uncaught ReferenceError: regeneratorRuntime is not defined
之后又看了一下转码之后的代码,确实找到了
第三次尝试,依赖再次添加,终于像点样子了。
# 你可以用下面的命令安装 yarn add @babel/core @babel/preset-env @rollup/plugin-babel @rollup/plugin-commonjs @rollup/plugin-node-resolve core-js rollup -D
// 下面是 rollup.config.js 文件的内容 import { babel } from '@rollup/plugin-babel'; import { nodeResolve } from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; export default { input: './src/index.js', output: { file: 'dist/index.js', format: 'iife' }, plugins: [ nodeResolve({ browser: true }), commonjs(), babel({ babelrc: false, exclude: /node_modules/, // @babel/preset-env 选项设置参考 https://babeljs.io/docs/en/babel-preset-env presets: [ ["@babel/preset-env", { useBuiltIns: "usage", corejs: { version: 3, proposals: true, }, // targets选项 参考:https://babeljs.io/docs/en/babel-preset-env#targets // targets: { // chrome: 96, // }, // targets: { // ie: 8 // }, targets: { browsers: ["last 2 versions"] } }] ], }) ] };
说明:采用上面的配置,像新增的Array.prototype.includes、Array.from、Set、Promise将会“转换”,这种方式会Array、Array.prototype或者window上补齐方法。 一般都推荐在自己的应用程序中使用,如果是通用的类库则不推荐使用这种方式
第四次尝试,和第三次差不多,都实现转换,各有利弊。
# 你可以用下面的命令安装 yarn add @babel/core @babel/plugin-transform-runtime @babel/preset-env @babel/runtime @babel/runtime-corejs3 @rollup/plugin-babel @rollup/plugin-commonjs @rollup/plugin-node-resolve rollup -D
// 下面是 rollup.config.js 文件的内容 import { babel } from '@rollup/plugin-babel'; import { nodeResolve } from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; export default { input: './src/index.js', output: { file: 'dist/index.js', format: 'iife' }, plugins: [ nodeResolve({ browser: true }), commonjs(), babel({ babelrc: false, exclude: /node_modules/, babelHelpers: 'runtime', presets: ['@babel/preset-env'], plugins: [ ['@babel/plugin-transform-runtime', { corejs: { version: 3, proposals: true }, useESModules: true }] ] }) ] };
说明:这种方式没有在Array、Array.prototype或者window上补齐缺少的方法而是重命名(或者叫做替换)的方式。这种方式对大环境没有影响。
综合第三次和第四次的优点, GitHub - babel/babel-polyfills: A set of Babel plugins that enable injecting different polyfills with different strategies in your compiled code. 我们期待他的到来……
上一章节是使用配置文件处理的,这一章节介绍一下使用API处理。为了做一下对比,上面的配置也修改一下来生成map文件,这里是在“第四次尝试”的基础上进行修改。先看一下修改之后的配置:
// 下面是 rollup.config.js 文件的内容 import { babel } from '@rollup/plugin-babel'; import { nodeResolve } from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; export default { input: './src/index.js', output: { file: 'dist/index.js', format: 'iife', sourcemap: true, // 和“第四次尝试”对比新增的选项 }, plugins: [ nodeResolve({ browser: true }), commonjs(), babel({ babelrc: false, exclude: /node_modules/, babelHelpers: 'runtime', presets: ['@babel/preset-env'], plugins: [ ['@babel/plugin-transform-runtime', { corejs: { version: 3, proposals: true }, useESModules: true }] ] }) ] };
赶紧试试吧!先生成一个,方便后面的对比,看看是不是一样。
下面就切入正题,介绍一下使用API。其实关于rollup的配置,就是拆分成了两部分:输入选项和输出选项;之后就是调用rollup的API了;最后就是将返回的内容写入文件了……这里新建一个"build.js"文件,和"rollup.config.js"文件同级
// 下面是 build.js 文件的内容 const rollup = require("rollup"); const { babel } = require("@rollup/plugin-babel"); const { nodeResolve } = require("@rollup/plugin-node-resolve"); const commonjs = require("@rollup/plugin-commonjs"); const fs = require("fs"); if (!fs.existsSync("dist")) { fs.mkdirSync("dist"); } const inputOptions = { input: './src/index.js', plugins: [ nodeResolve({ browser: true }), commonjs(), babel({ babelrc: false, exclude: /node_modules/, babelHelpers: 'runtime', presets: ['@babel/preset-env'], plugins: [ ['@babel/plugin-transform-runtime', { corejs: { version: 3, proposals: true }, useESModules: true }] ] }) ] }; const outputOptions = { file: 'dist/index.js', format: 'iife', sourcemap: true, }; rollup.rollup(inputOptions).then((bundle) => { bundle.generate(outputOptions).then((outputData) => { let { output: [{ code, map }], } = outputData, // 暂时先这样获取文件名 outputFileName = outputOptions.file.slice(outputOptions.file.lastIndexOf("/") + 1), jsMapFileName = ""; // 对于map先这样处理,暂时不考虑sourcemapFile if (outputOptions.sourcemap) { code += `//# sourceMappingURL=${outputFileName}.map`; jsMapFileName = outputOptions.file + ".map"; } fs.writeFile(outputOptions.file, code, (err) => { console.log(JSON.stringify(err)); }); if (outputOptions.sourcemap) { fs.writeFile( jsMapFileName, JSON.stringify(map), (err) => { console.log(JSON.stringify(err)); } ); } }); });
之后在控制台执行