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

相关推荐
佛系菜狗3 分钟前
element-ui、element-plus表单resetFields()无效的坑
前端·javascript·vue.js
爱的叹息24 分钟前
【前端】基于 Promise 的 HTTP 客户端工具Axios 详解
前端·网络·网络协议·http
遗憾随她而去.31 分钟前
从 0 开始认识 WebSocket:前端实时通信的利器!
前端·websocket·网络协议
老兵发新帖1 小时前
pnpm常见报错解决办法
前端
Sonetto19991 小时前
Nginx 反向代理,啥是“反向代理“啊,为啥叫“反向“代理?而不叫“正向”代理?它能干哈?
运维·前端·nginx
沐土Arvin1 小时前
理解npm的工作原理:优化你的项目依赖管理流程
开发语言·前端·javascript·设计模式·npm·node.js
好_快1 小时前
Lodash源码阅读-baseUniq
前端·javascript·源码阅读
不秃的开发媛1 小时前
前端技术Ajax入门
java·开发语言·前端
牧羊狼的狼2 小时前
React.memo 和 useMemo
前端·javascript·react.js
xixixin_2 小时前
【uniapp】vue2 搜索文字高亮显示
java·服务器·前端·uni-app·交互·文字高亮