使用jsx来编写模板
前言
模板引擎这个应该都不陌生,最早可以追溯到前后端还没分离的时候,后端为了循环、判断值之类简化编写流程而使用的,毕竟手动拼接字符串之类的也太麻烦了。
下面是 php easytpl 的一个示例,从这个可以看到模板引擎的基本用途。
use PhpPkg\EasyTpl\EasyTemplate;
$tplCode = <<<'CODE'
My name is {{ $name | strtoupper }},
My develop tags:
{{ foreach($tags as $tag) }}
- {{ $tag }}
{{ endforeach }}
CODE;
$t = new EasyTemplate();
$str = $t->renderString($tplCode, [
'name' => 'inhere',
'tags' => ['php', 'go', 'java'],
]);
echo $str;
上面这对代码会输出
My name is INHERE,
My develop tags:
- php
- go
- java
回到 JavaScript,随着职能的不断提升前端也面临同样的问题,于是社区涌现了一堆库,例如:
上面的几个使用方法都大同小异,都是通过内置一些语法来简化重复的书写。不过思考一下使用模板引擎会有什么缺点?
下面是一段 ejs 代码示例
<% if (resultPreSale.length) { %>
<h2>本次新增入网楼栋:<%= resultPreSale.length %>个</h2>
<ul>
<% resultPreSale.forEach(function(item){ %>
<li>
<p>
<a href="<%= item.url %>"> 项目名称:<%= item.entryName %> </a>
</p>
<p>楼幢号:<%= item.buildingNumber %></p>
<p>许可面积(㎡):<%= item.permittedArea %></p>
<p>发放日期:<%= item.time %></p>
</li>
<% }); %>
</ul>
<% } %>
从上面的示例可以看到以下缺点:
- 缺少语法提示:在使用编辑器的时候使用相对应语法都会有提示,但是上面在使用
forEach
之类的根本不会有提示; - 不能借助 Eslint、TypeScript 来提前检查编写错误:例如有一些 props 没有传递或者类型缺少,以及变量不存在而引用等错误,必须运行之后才会发现错误;
- 有额外的学习成本,每个模板引擎的语法其实都不一样,例如 ejs 和 pug 就不一致;
jsx
回归到最熟悉的 jsx 本身,得益于 React 的流行 jsx 这种灵活方便的语法就是首选,首先生态很丰富可以跟 TypeScript 和 eslint 无缝衔接,且语法跟 js 基本一致不会增加额外的学习成本,且跟编辑器配合很好可以有语法提示。
下面是一段示例
const App = (props: Props) => {
return (
<>
<PreSale resultPreSale={props.resultPreSale}></PreSale>
<List resultList={props.resultList}></List>
<List resultList={props.residueList} title={<h2>其他正在摇号项目({props.residueList.length}个):</h2>}></List>
<p>本次爬取时间:{props.currentTime}</p>
<style>{style}</style>
</>
);
};
jsx 基础的语法和如何解析这里并不关心,说回主题如何使用 jsx 来编写模板呢?
解析 jsx
模板返回的都是字符串的形式,但是上面示例的 App 明显是一个函数,所以首先需要把 jsx 转换为字符串,幸运的是社区有相关的库,这里使用的是 preact-render-to-string,preact是一个跟 React 实现很接近的库,你可以理解为 mini React。
这里其实并不会使用 hooks 之类的功能,使用的只是 jsx 语法本身,所以选用什么框架并不关键。
import { render } from 'preact-render-to-string';
const html = render(<App {...props}></App>);
如果结合 TypeScript 使用,还需要做一些额外的配置
-
安装 preact
-
修改 tsconfig.json
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "preact"
}
}
node 环境使用
这里并没有万事大吉,在 node 环境使用模板引擎也是一个很正常的事情,但是 tsx 或者 jsx 文件都是属于需要编译来进行处理的,否则 node 并不认识。
- tsx,使用 tsx 这个库,它通过 esbuild 来运行 TypeScript 和 ESM 文件;
- webpack
下面是一个完整的 webpack 示例
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const RunNodeWebpackPlugin = require('run-node-webpack-plugin');
module.exports = {
entry: {
index: './src/index.ts',
},
target: 'node',
devtool: 'source-map',
externalsPresets: { node: true },
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].cjs',
clean: true,
},
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
module: {
rules: [
{
test: /\.(js|jsx|ts|tsx)$/,
exclude: /node_modules/,
use: [
{
loader: 'esbuild-loader',
options: {
target: 'es2022',
},
},
],
},
],
},
};
最后
如果文章有错误欢迎留言指出。
转载自:https://juejin.cn/post/7241830754056781883