编译JSX
问题
OA系统前端使用React开发,我们的业务代码中也会写React组件。React组件通常用JSX语法编写(形如<Component/>),然后编译成原生JS语法(形如React.createElement(Component, ...))。我们的开发框架目前对JS代码只是简单地组装,浏览器运行的就是我们直接写出来的代码,因此在JS源文件中只能写原生JS语法,这对编写React组件很不方便。因此,开发框架需要支持JSX语法的编译。
技术选型
使用Babel实现将JSX语法编译为原生JS语法。
兼容性
JSX语法是原生JS语法的超集,IDE支持在.js扩展名的源文件中使用JSX语法,因此,我们直接将已有的index.js统一看作JSX语法,统一将其编译为原生JS语法。
实现
安装依赖@babel/core、@babel/preset-react。
修改构建程序:
const babel = require("@babel/core");
/** 编译JSX语法为原生JS语法 */
function compileJSX(code) {
const OPTIONS = {
presets: ["@babel/preset-react"],
};
return babel.transformSync(code, OPTIONS).code;
}
/** 获取JS代码 */
function getJS(scriptDirPath) {
const jsxFilePath = path.resolve(scriptDirPath, "index.js");
const jsx = fs.readFileSync(jsxFilePath, {encoding: "UTF-8"});
return compileJSX(jsx);
}
// 构建时
const js = getJS(scriptDirPath);
编译SCSS
问题
用原生CSS语法写复杂样式时很麻烦,因此我们希望通过CSS预处理器(CSS preprocesssor)来降低复杂性。
技术选型
使用Sass的SCSS语法,它是原生CSS语法的超集,增加了嵌套、变量、单行注释等方便的特性,易学易用易读。
使用sass库将SCSS语法编译为原生CSS语法。
兼容性
之前已经写了不少index.css,但这里不能像JS那样,直接将.css的内容看作SCSS语法,因为IDE不支持,会报错。
我们有两种解决办法:
- 将所有
index.css全部改名为index.scss,然后开发框架只支持index.scss,并要求团队以后必须使用index.scss这个名称,这样更简单。 - 同时支持
index.css(原生CSS语法)和index.scss(SCSS语法),并规定index.scss优先于index.css,这样两种名称都可以用。
考虑到团队的实际情况,考虑到所有人都熟悉CSS但并非所有人都熟悉SCSS,考虑到SCSS只在少数复杂场景下使用才有必要,那么,应该保留对index.css的支持。
实现
安装依赖sass。
修改构建程序:
const sass = require("sass");
/** 编译SCSS语法为原生CSS语法 */
function compileSCSS(code) {
return sass.compileString(code).css;
}
/** 获取CSS代码 */
function getCSS(scriptDirPath) {
const scssFilePath = path.resolve(scriptDirPath, "index.scss");
const cssFilePath = path.resolve(scriptDirPath, "index.css");
if (fs.existsSync(scssFilePath)) {
const scss = fs.readFileSync(scssFilePath, {encoding: "UTF-8"});
return compileSCSS(scss);
} else if (fs.existsSync(cssFilePath)) {
return fs.readFileSync(cssFilePath, {encoding: "UTF-8"});
} else {
return "";
}
}
// 构建时
const css = getCSS(scriptDirPath);
异常处理
之前的构建只是简单地读取、组装,所以一直没有遇到构建失败的情况。但在支持JSX和SCSS的编译后,构建就不一定能成功了,比如SCSS代码中有语法错误,编译时就会抛异常,导致整个构建程序退出。
因此,要在构建脚本目录时做异常处理,在控制台中报告构建失败,并打印异常。