内联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


相关文章
|
4月前
|
JavaScript 前端开发 编译器
解锁JavaScript模块化编程新纪元:从CommonJS的基石到ES Modules的飞跃,探索代码组织的艺术与科学
【8月更文挑战第27天】随着Web应用复杂度的提升,JavaScript模块化编程变得至关重要,它能有效降低代码耦合度并提高项目可维护性及扩展性。从CommonJS到ES Modules,模块化标准经历了显著的发展。CommonJS最初专为服务器端设计,通过`require()`同步加载模块。而ES Modules作为官方标准,支持异步加载,更适合浏览器环境,并且能够进行静态分析以优化性能。这两种标准各有特色,但ES Modules凭借其更广泛的跨平台兼容性和现代语法逐渐成为主流。这一演进不仅标志着JavaScript模块化的成熟,也反映了整个JavaScript生态系统的不断完善。
54 3
|
4月前
|
存储 JavaScript 前端开发
Node.js的基本语法
【8月更文挑战第12天】Node.js的基本语法
154 1
|
2月前
|
JavaScript 前端开发
JavaScript 函数语法
JavaScript 函数是使用 `function` 关键词定义的代码块,可在调用时执行特定任务。函数可以无参或带参,参数用于传递值并在函数内部使用。函数调用可在事件触发时进行,如用户点击按钮。JavaScript 对大小写敏感,函数名和关键词必须严格匹配。示例中展示了如何通过不同参数调用函数以生成不同的输出。
|
3月前
|
缓存 JavaScript 中间件
优化Express.js应用程序性能:缓存策略、请求压缩和路由匹配
在开发Express.js应用时,采用合理的缓存策略、请求压缩及优化路由匹配可大幅提升性能。本文介绍如何利用`express.static`实现缓存、`compression`中间件压缩响应数据,并通过精确匹配、模块化路由及参数化路由提高路由处理效率,从而打造高效应用。
195 14
|
2月前
|
JavaScript 前端开发 大数据
在JavaScript中,Object.assign()方法或展开语法(...)来合并对象,Object.freeze()方法来冻结对象,防止对象被修改
在JavaScript中,Object.assign()方法或展开语法(...)来合并对象,Object.freeze()方法来冻结对象,防止对象被修改
36 0
|
3月前
|
存储 JavaScript 前端开发
[JS] ES Modules的运作原理
【9月更文挑战第16天】ES Modules(ECMAScript Modules)是 JavaScript 中的一种模块化开发规范,适用于浏览器和 Node.js 环境。它通过 `export` 和 `import` 关键字实现模块的导出与导入。模块定义清晰,便于维护和测试。JavaScript 引擎会在执行前进行静态分析,确保模块按需加载,并处理循环依赖。ES Modules 支持静态类型检查,现代浏览器已原生支持,还提供动态导入功能,增强了代码的灵活性和性能。这一规范显著提升了代码的组织和管理效率。
|
4月前
|
JavaScript 前端开发
JavaScript基础&实战(1)js的基本语法、标识符、数据类型
这篇文章是JavaScript基础与实战教程的第一部分,涵盖了JavaScript的基本语法、标识符、数据类型以及如何进行强制类型转换,通过代码示例介绍了JS的输出语句、编写位置和数据类型转换方法。
JavaScript基础&实战(1)js的基本语法、标识符、数据类型
|
4月前
|
JavaScript 前端开发 安全
JS 混淆解析:JS 压缩混淆原理、OB 混淆特性、OB 混淆JS、混淆突破实战
JS 混淆解析:JS 压缩混淆原理、OB 混淆特性、OB 混淆JS、混淆突破实战
236 2
|
4月前
|
前端开发 JavaScript 程序员
前端 JavaScript 的 _ 语法是个什么鬼?
前端 JavaScript 的 _ 语法是个什么鬼?
|
5月前
|
缓存 JavaScript 前端开发
前端框架与库 - Vue.js基础:模板语法、数据绑定
【7月更文挑战第14天】Vue.js 是渐进式框架,以简洁API和高效数据绑定知名。本文聚焦模板语法与数据绑定,解释常见问题和易错点,助力初学者避坑。模板语法中,{{ expression }} 用于渲染值,v-bind/: 用于动态绑定属性。数据绑定涉及文本、属性和事件,注意v-model适用于表单元素,计算属性有缓存。理解正确用法,借助文档和IDE,可提升开发质量和效率。善用Vue.js,打造响应式UI。
169 4