使用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也是空实现,看来大家的思路都是相同的,浏览器办不到的就不实现,保证能正常编译就行了。

相关推荐
卸任19 小时前
Vibe coding工具使用心得
前端·ai编程
brien920 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance20 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M20 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写20 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李20 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易20 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
风骏时光牛马20 小时前
前沿视界
前端
kyriewen20 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员
陈随易21 小时前
3000 万人在用的翻译插件,重写一遍就是一门生意
前端·后端·程序员