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

相关推荐
fruge3 小时前
Vue项目中的Electron桌面应用开发实践指南
前端·vue.js·electron
漂流瓶jz8 小时前
Webpack中各种devtool配置的含义与SourceMap生成逻辑
前端·javascript·webpack
前端架构师-老李9 小时前
React 中 useCallback 的基本使用和原理解析
前端·react.js·前端框架
木易 士心9 小时前
CSS 中 `data-status` 的使用详解
前端·css
明月与玄武9 小时前
前端缓存战争:回车与刷新按钮的终极对决!
前端·缓存·回车 vs 点击刷新
牧马少女9 小时前
css 画一个圆角渐变色边框
前端·css
zy happy10 小时前
RuoyiApp 在vuex,state存储nickname vue2
前端·javascript·小程序·uni-app·vue·ruoyi
小雨青年10 小时前
Cursor 项目实战:AI播客策划助手(二)—— 多轮交互打磨播客文案的技术实现与实践
前端·人工智能·状态模式·交互
小光学长10 小时前
基于Vue的儿童手工创意店管理系统as8celp7(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
前端·数据库·vue.js
meichaoWen10 小时前
【Vue】Vue框架的基础知识强化
前端·javascript·vue.js