内联JS处理(ES语法降级&内容压缩)(2)

简介: 小结这部分除了正则外,介绍了3个可以用来提取inline js库(gogocode,svelte,posthtml)从专业程度来看posthtml更加合适,拓展起来也方便,后面的功能也将基于其直接开发插件,方便复用。使用SWC处理SWC 是一个可以用于替换babel的工具,基于Rust实现,在单线程上比 Babel 快20倍。

内联JS处理(ES语法降级&内容压缩)(1):https://developer.aliyun.com/article/1394845?spm=a2c6h.13148508.setting.14.55964f0ez7IHhI

小结

这部分除了正则外,介绍了3个可以用来提取inline js库(gogocodesvelteposthtml

从专业程度来看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个posthtmlSWCMinifyposthtmlSWCTransform2个方法,用于压缩和转换两个场景

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个指令transformminify,只包含上述方法的基本的传入参数

#!/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)

image.png 

指令实现

下面是 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

image.png

ijs transform __test__/test.html --minify

image.png

最后

文章中涉及示例代码以及工具完整源码见 GitHub


相关文章
|
2天前
|
JavaScript 前端开发 开发者
Vue.js 模板语法
Vue.js 模板语法
|
2月前
|
JavaScript 前端开发 Web App开发
JavaScript基础语法(codewhy版本)(一)
JavaScript基础语法(codewhy版本)
90 1
JavaScript基础语法(codewhy版本)(一)
|
2月前
|
JavaScript 前端开发 算法
JavaScript基础语法(codewhy版本)(二)
JavaScript基础语法(codewhy版本)
20 0
JavaScript基础语法(codewhy版本)(二)
|
2月前
|
JavaScript 前端开发 网络架构
JavaScript的数组教程(最详细,更新至es6新语法)
JavaScript的数组教程(最详细,更新至es6新语法)
|
2月前
|
移动开发 前端开发 JavaScript
Java 和 JavaScript 的奇妙协同:语法结构的对比与探索(下)
Java 和 JavaScript 的奇妙协同:语法结构的对比与探索(下)
|
2月前
|
JavaScript 前端开发 Java
Java 和 JavaScript 的奇妙协同:语法结构的对比与探索(中)
Java 和 JavaScript 的奇妙协同:语法结构的对比与探索(中)
|
2月前
|
JavaScript 前端开发 Java
Java 和 JavaScript 的奇妙协同:语法结构的对比与探索(上)
Java 和 JavaScript 的奇妙协同:语法结构的对比与探索(上)
|
存储 JSON JavaScript
使用JavaScript ES6的新特性计算Fibonacci(非波拉契数列)
使用JavaScript ES6的新特性计算Fibonacci(非波拉契数列)
116 0
使用JavaScript ES6的新特性计算Fibonacci(非波拉契数列)
|
2天前
|
存储 移动开发 JavaScript
学习javascript,前端知识精讲,助力你轻松掌握
学习javascript,前端知识精讲,助力你轻松掌握