如何在NPM模块中打包静态数据资产以支持浏览器React项目调用
解决方案
你可以通过构建阶段预加载内联数据的方式替换运行时fs读取逻辑,以下是两种可落地的实现方案:
方案1:预构建生成静态数据文件(无构建配置依赖,适配所有打包工具)
这个方案通过前置脚本提前解码数据并生成可直接导入的JS文件,完全规避运行时的Node API调用:
- 项目根目录新建
prebuild.js预构建脚本,代码如下:
import { decode } from "@msgpack/msgpack"; import { readFileSync, writeFileSync } from "fs"; import path from "path"; // 读取原始数据文件并解码 const file = readFileSync(path.join(__dirname, "./assets/systems.dat")); const systems = decode(file); // 生成可直接导入的ESM格式数据文件 writeFileSync( path.join(__dirname, "./src/generated-systems.js"), `export default ${JSON.stringify(systems)};` );
- 修改
package.json的脚本配置,让预构建脚本在打包前自动执行:
{ "scripts": { "prebuild": "node prebuild.js", "build": "你原本的打包命令,比如tsup、rollup等" } }
- 替换原有的模块实现代码:
import systems from "./generated-systems.js"; export const getSystems = () => systems;
方案2:Rollup/Vite 自定义插件(适配基于Rollup的打包链路)
如果你用Rollup或者Vite作为打包工具,可以通过自定义插件直接处理.dat后缀的文件,在打包阶段自动完成解码内联:
- 在Rollup/Vite配置中添加自定义插件:
// rollup.config.js 或 vite.config.js import { decode } from "@msgpack/msgpack"; import { readFileSync } from "fs"; export default { // 其余原有配置保持不变 plugins: [ { name: 'msgpack-dat-loader', transform(_, id) { if (id.endsWith('.dat')) { const file = readFileSync(id); const systems = decode(file); return `export default ${JSON.stringify(systems)};`; } } }, // 其余原有插件保持不变 ] }
- 替换原有的模块实现代码:
import systems from "../assets/systems.dat"; export const getSystems = () => systems;
大数据量优化方案
如果你的systems.dat体积偏大,用JSON.stringify序列化会导致产物体积过大,可以选择内联base64格式的二进制数据,运行时再解码,能有效压缩产物体积:
预构建脚本修改为如下内容即可:
import { readFileSync, writeFileSync } from "fs"; import path from "path"; const file = readFileSync(path.join(__dirname, "./assets/systems.dat")); const base64Data = file.toString('base64'); writeFileSync( path.join(__dirname, "./src/generated-systems.js"), `import { decode } from "@msgpack/msgpack"; const binary = Uint8Array.from(atob("${base64Data}"), c => c.charCodeAt(0)); export default decode(binary);` );
内容的提问来源于stack exchange,提问作者basse
相关产品推荐
相关产品推荐

