使用webpack.resolve.alias替换express,保证可以正常构建出web版本

需求背景

ts 复制代码
import { readFileSync } from "fs"

我们知道,web是不支持nodejs fs模块,更不能读取磁盘文件,但是如果我要使用webpack打包为web版本,以上的代码是肯定过不去的。

所以我不得不在代码中作如下判断

ts 复制代码
if (!isWeb) {
     const { readFileSync } = require("fs")
     // ...
}

是的,我判断在非web环境我才调用引入fs模块,并且使用相关的api,这样也能解决问题。

但是当情况复杂起来,这样解决方案就行不通了,会让代码难以维护。

比如以下的情况,期望的代码是如下,也能正常通过webpack的打包

ts 复制代码
import express, { Express } from "express"

let expressInstance: Express | null = null;
if(!isWeb){
    expressInstance = express();
}

很明显express是不支持web环境的,所以你可能会这么改

ts 复制代码
let expressInstance = null; // 变量的类型标注丢失
if(!isWeb){
    const express = require("express"); // 在ts里面写require,让代码很蹩脚
    expressInstance = express();
}

怎么看,这个代码都不是太尽如人意,而且上边的2个问题,就是让代码难以维护的罪魁祸首。

因为我的cc-plugin是可以同时发布web版本和nodejs版本,所以才出现这么奇葩的需求。

解决办法

让我再阐明下我的需求,我希望代码完全的使用typescript易于维护,并且webpack能够自动兼容一些nodejs的本地接口,这些接口在web环境不实现也行,其实压根也实现不了。

因为有isWeb的判断,所以从代码编写角度来说,以下的写法肯定是最优解

ts 复制代码
import express, { Express } from "express"

let expressInstance: Express | null = null;
if(!isWeb){
    expressInstance = express();
}

那问题就指向了,有什么办法可以让预期的代码通过webpack编译呢?

如果你对webpack非常熟悉,肯定知道fallback,有许多nodejs的模块都有对应的browserify,可以让其在浏览器环境正常运行。

browserify简单来说,其原理就是使用纯js实现对应模块的api,保证其在浏览器里面也能正常工作,这和游戏引擎跨平台的道理是一样的。

而这里我的需求是仅仅保证webpack能通过编译即可,在web环境里面,我是不会调用到express的相关api的,顺着这个思路想下去,再结合fallback的思想,很自然的我就想到了解决办法:

实现一个express的browserify,相关的接口全部为空实现,这样就能保证webpack能够正常编译,而且能够正常import "express",虽然这样导入的express模块是一个空壳,但是我代码层面在web环境是不会调用到相关接口的,所以这样子也算解决了我的问题。

在webpack里面强制替换模块,使用的是webpack resolve alias,所以在webpack配置里面

json 复制代码
{
    resolve:{
        alias:{
            "express": "express-browserify"
        }
    }
}

当打包web版本时,使用以上配置,node版本时,还正常使用express,这样子就不用来回改代码了,至此问题就完美解决了,以下是我写的几个模块的browserify空实现

总结

其实我看了几个fallback的browserify,并不是所有的nodejs本地api都支持了,有些browserify也是空实现,看来大家的思路都是相同的,浏览器办不到的就不实现,保证能正常编译就行了。

相关推荐
y先森5 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy5 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189115 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿6 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡7 小时前
commitlint校验git提交信息
前端
虾球xz7 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇7 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒7 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员8 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐8 小时前
前端图像处理(一)
前端