内联JS处理(ES语法降级&内容压缩)(1):https://developer.aliyun.com/article/1394845?spm=a2c6h.13148508.setting.14.55964f0ez7IHhI
小结
这部分除了正则
外,介绍了3个可以用来提取inline js
库(gogocode
,svelte
,posthtml
)
从专业程度来看posthtml
更加合适,拓展起来也方便,后面的功能也将基于其直接开发插件,方便复用。
使用SWC处理
SWC 是一个可以用于替换babel的工具,基于Rust实现,在单线程上比 Babel 快20倍。
前面主要阐述了html中js代码的提取,这个部分就简单阐述一下使用SWC
对js部分代码进行ES语法降级
与压缩
。
直接利用transformSync方法对代码进行语法降级
- jsc:js代码编译相关配置
- minify:是否压缩
import { transformSync } from '@swc/core' import type { JscTarget } from '@swc/core' export function transformCode( code: string, target: JscTarget = 'es5', minify = false ) { return transformSync(code, { jsc: { target }, minify }).code }
minifySync直接对代码进行压缩处理。
- compress参数:可用于更细粒度的控制压缩策略
- mangle参数:细粒度的控制代码混淆策略
由于在HTML中的JS 代码可能会被后续的script
所引用。所以关掉混淆策略,避免影响代码正常工作
例如
const hello = 'hello' // 开启混淆后结果是 var l="hello";
import { minifySync } from '@swc/core' import type { JsMinifyOptions } from '@swc/core' export function minifyCode(code: string, ops?: JsMinifyOptions) { return minifySync(code, { compress: false, mangle: false, ...ops }).code }
其它压缩相关的细节参数这里就不展开介绍了,可以看结合文档介绍和官方的playground进行实践验证
posthtml插件封装
这里就封装2个posthtmlSWCMinify
和posthtmlSWCTransform
2个方法,用于压缩和转换两个场景
export function posthtmlSWCTransform( target: JscTarget = 'es5', minify = false ) { return (tree: Node) => { tree.match({ tag: 'script' }, (node) => { if (node?.content?.[0]) { node.content[0] = transformCode( node.content[0].toString(), target, minify ) } return node }) } } export function posthtmlSWCMinify(ops?: JsMinifyOptions) { return (tree: Node) => { tree.match({ tag: 'script' }, (node) => { if (node?.content?.[0]) { node.content[0] = minifyCode(node.content[0].toString(), ops) } return node }) } }
使用示例如下
import posthtml from 'posthtml' posthtml() .use(posthtmlSWCTransform()) .process(htmlCode, { sync: true }) posthtml() .use(posthtmlSWCMinify()) .process(htmlCode, { sync: true })
至此对HTML
中inlineJS的提取与使用SWC
处理的方法进行了较为详细的阐述,下面就是通过CLI组合能力,然后对外提供使用。
CLI封装
通过封装一个简单的CLI工具,直接对目标HTML进行转换,调用起来更加的便捷,也方便的在现有工程中集成。
参数定义
使用commander
做参数解析,先定义一下指令和传参,就2个指令transform
和minify
,只包含上述方法的基本的传入参数
#!/usr/bin/env node import { Command } from 'commander' import pkg from '../package.json' import { minifyCommand, transformCommand } from './command' const program = new Command() program.version(pkg.version) program .command('transform [paths...]') .description('transform inlineJS code ESVersion by SWC') .alias('t') .option( '-e, --ecmaVersion [ecmaVersion]', 'set transform jsc target version', 'es5' ) .option('-m, --minify', 'minify transform result') .action(transformCommand) program .command('minify [paths...]') .description('minify inlineJS code by SWC') .alias('m') .action(minifyCommand) program.parse(process.argv)
指令实现
下面是 transformCommand
的简单实现
- 使用
fs
模块读写文件内容 - 直接通过
posthtml
调用前面实现的posthtmlSWCTransform
插件对内容进行转换
// transformCommand import fs from 'fs' import type { JscTarget } from '@swc/core' import posthtml from 'posthtml' import { posthtmlSWCTransform } from '../index' interface Options { ecmaVersion?: JscTarget minify?: boolean } export default function transformCommand(filesArg: string[], options: Options) { for (const filepath of filesArg) { const content = fs.readFileSync(filepath, 'utf-8') const result = posthtml() .use(posthtmlSWCTransform(options.ecmaVersion || 'es5', !!options.minify)) .process(content, { sync: true }).html fs.writeFileSync(filepath, result, 'utf-8') } }
minifyCommand
的实现是类似的这里就不再赘述。
效果
安装 npm i -g @sugarat/inlinejs-transform
ijs minify __test__/test.html
ijs transform __test__/test.html --minify
最后
文章中涉及示例代码以及工具完整源码见 GitHub