Ошибка: не удается разрешить 'fs' в изоморфном приложении JS - PullRequest
0 голосов
/ 23 апреля 2019

Я создаю пакет Typescript, который должен работать как на переднем, так и на заднем концах. Я использую этот пакет, чтобы узнать, является ли среда браузером или узлом: https://www.npmjs.com/package/browser-or-node Точка входа - один файл index.js

Я могу создать и опубликовать приложение без проблем, однако, когда я импортирую его и пытаюсь запустить его в браузере, я получаю сообщение об ошибке Module not found: Error: Can't resolve 'fs'

Похоже, это связано с тем, что я импортирую fs, который является методом узла, а браузер не знает, что делать.

Какова наилучшая практика в этом случае, чтобы избежать этой проблемы? Если я не импортирую этот модуль, библиотека будет работать нормально.

Мой пакет.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')
    }
}

1 Ответ

0 голосов
/ 23 апреля 2019

Основной ответ заключается в том, что вы можете использовать поле "browser" package.json , чтобы исключить модуль из комплектов браузера.Он поддерживается всеми основными компоновщиками.

{
  "browser": {
    "fs": false
  }
}

Затем, в browserify, вы получите пустой объект при импорте fs.Я не уверен, что делают другие упаковщики!


Но вы можете сделать это немного по-другому и избежать необходимости в пакете браузера или узла.У вас может быть два файла для реализации узла и браузера для хранения токенов.Например,

// token-storage.js
import * as fs from "fs"
export function saveTokens() { /* Node implementation */ }

// token-storage.browser.js
export function saveTokens() { /* localStorage implementation */ }

Вы можете переключаться между ними, снова используя поле "browser".

{
  "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.Он сохраняет решение узла / браузера локализованным в файле хранилища токенов, и вам не нужно думать об этом, когда вы используете его где-либо еще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...