支持jsx的脚本工程模板(构建产物很小)

116 阅读2分钟

废话少说,先上模板地址:github.com/Potato-DiGu…

众所周知在web页面中打开控制台就可以注入js脚本获取信息或增加功能,但是想在页面中用js插入UI就要用document.createElement去嵌套生成dom,比较繁琐。而react的JSX生来就是要解决这个问题的,但是react这个库太重了,写个脚本用不到。就找了其他的JSX实现。

为了以后方便复用就有了这个模板。模板中的jsx框架可以一键切换,支持如下框架:

框架说明推荐使用范围构建命令
dom-chef仅实现了jsx的createElement方法,不支持UI自动更新只需要简单的UI控制脚本逻辑,不需要进行复杂的状态管理和UI更新pnpm run build:domchef
preactreact的极小实现, 只有3KB需要复杂的UI控制脚本逻辑pnpm run build:preact

框架切换实现原理

两个包都是按照JSX的标准实现的,切换很简单,只要把引入的包替换一下就行,正好打包工具就支持构建时替换引入的包名,本项目是用rollup打包的,利用@rollup/plugin-alias就能实现。

将两个包的构建配置放到frameconfig.js中,关键配置在于rollupAlias,两种配置通过环境变量切换,这样就能在打包的时候根据传入的环境变量使用不同的配置

const config = {
    domchef: {
        reactBabelConfig: {
            //   pragma: "h", // default pragma is React.createElement (only in classic runtime)
            //   pragmaFrag: 'DocumentFragment',
        },
        rollupAlias: [
            // react引入替换为dom-chef
            { find: 'react', replacement: 'dom-chef' },
        ],
    },
    preact: {
        reactBabelConfig: {
            pragma: 'h',
            pragmaFrag: 'Fragment',
        },
        rollupAlias: [
            // react引入替换为preact
            { find: 'react', replacement: 'preact/compat' },
            { find: 'react-dom/test-utils', replacement: 'preact/test-utils' },
            { find: 'react-dom', replacement: 'preact/compat' },
            { find: 'react/jsx-runtime', replacement: 'preact/jsx-runtime' },
        ],
    },
};

const supportFrames = Object.keys(config);
const frameWork = process.env.FRAME_WORK?.trim()?.toLowerCase();
if (!supportFrames.includes(frameWork)) {
    throw new Error(`not support ${frameWork},frameWork only support ${supportFrames.join(', ')}`);
}

module.exports = config[frameWork];

rollup配置文件,如果在代码中使用了process.env需要在@rollup/plugin-replace中替换,因为这个process.env只有在构建时才有值,在浏览器中访问不到。

import resolve from '@rollup/plugin-node-resolve';
import babel from '@rollup/plugin-babel';
import typescript from '@rollup/plugin-typescript';
import commonjs from '@rollup/plugin-commonjs';
import terser from '@rollup/plugin-terser';
import alias from '@rollup/plugin-alias';
import replace from '@rollup/plugin-replace';

const frameConfig = require('./frameconfig');

export default {
    //...
    plugins: [
        replace({
            'process.env.FRAME_WORK': `'${process.env.FRAME_WORK}'`,
        }),
        resolve(),
        commonjs(),
        alias({
            entries: [...frameConfig.rollupAlias],
        }),
        typescript(),
        babel({ babelHelpers: 'bundled' }),
    ],
};

本项目的示例代码构建产物大小对比

框架大小
dom-chef4KB
preact22KB(说好的3KB呢)