我正在构建一个应该同时在前端和后端运行的Typescript软件包。我正在使用此软件包来识别环境是浏览器还是节点: https://www.npmjs.com/package/browser-or-node 入口点是单个index.js文件
我可以毫无问题地构建和发布应用程序,但是当我导入它并尝试在浏览器中运行它时,我收到错误消息
Module not found: Error: Can't resolve 'fs'
这似乎来自以下事实:我正在导入fs,这是一个节点方法,而浏览器不知道该怎么做。
在这种情况下,避免此问题的最佳做法是什么?如果我不导入该模块,那么该库就可以正常工作。
我的package.json:
"license": "MIT",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc",
"test": "mocha -r ts-node/register src/**/*.spec.ts"
},
"devDependencies": {
"@types/chai": "^4.1.7",
"@types/mocha": "^5.2.6",
"@types/sinon": "^7.0.11",
"@types/sinon-chai": "^3.2.2",
"chai": "^4.2.0",
"mocha": "^6.1.4",
"sinon": "^7.3.2",
"sinon-chai": "^3.3.0",
"ts-node": "^8.1.0",
"typescript": "^3.4.4"
},
"dependencies": {
"@types/es6-promise": "^3.3.0",
"axios": "^0.18.0",
"browser-or-node": "^1.2.1",
"dotenv": "^7.0.0"
}
我的tsconfig.json:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"declaration": true,
"outDir": "./dist",
"strict": true,
"noImplicitAny": false,
"lib": [ "es2015" ]
},
"exclude":[
"node_modules",
"./dist",
"./**/*.spec.ts",
"./test/**/*.ts"
]
}
引起问题的函数:
import * as fs from 'fs';
export function saveTokensNode(data: any, path: string) {
try {
fs.writeFileSync(path, JSON.stringify(data))
} catch (err) {
console.error(err)
}
}
我在哪里使用它:
setCredentials(tokens) {
if (isBrowser) {
saveTokensStorage(tokens)
}
if (isNode) {
saveTokensNode(tokens, 'temp/tokensToStore.json')
}
}
答案 0 :(得分:0)
基本答案是,您可以使用"browser" package.json field从浏览器包中排除模块。所有主要的捆绑软件都支持它。
{
"browser": {
"fs": false
}
}
然后,在浏览器中,导入fs
时将得到一个空对象。不过,我不确定其他捆绑器还能做什么!
但是您实际上可以稍微做些不同,从而避免需要浏览器或节点程序包。您可能有两个文件用于令牌存储的节点和浏览器实现。例如,
// token-storage.js
import * as fs from "fs"
export function saveTokens() { /* Node implementation */ }
// token-storage.browser.js
export function saveTokens() { /* localStorage implementation */ }
您可以再次使用“浏览器”字段在它们之间进行切换。
{
"browser": {
"./path/to/token-storage.js": "./path/to/token-storage.browser.js"
}
}
然后,在您的模块中,您可以执行以下操作:
import { saveTokens } from "./token-storage.js"
function setCredentials (tokens) {
saveTokens(tokens, 'temp/tokensToStore.json')
}
浏览器实现可以忽略文件路径,或将其用作localStorage密钥名称。它将节点/浏览器决策本地化为令牌存储文件,并且在其他任何地方使用它时都无需考虑。