废话少说,先上模板地址: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 |
| preact | react的极小实现, 只有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-chef | 4KB |
| preact | 22KB(说好的3KB呢) |