升级至Angular v6 - 模块未找到:错误:无法解决'fs'

38

我正在尝试将我的Angular Universal项目从Angular v5迁移到v6。

我有一个服务,其中我使用fs在服务器端加载翻译。 在Angular v5中一切正常。

但是,在Angular v6中,当我运行npm run start或者ng serve --proxy-config proxy.conf.json时,我遇到了以下错误:

ERROR in ./src/providers/core/translate/translate-universal-loader.service.ts Module not found: Error: Can't resolve 'fs' in '/Users/me/Documents/projects/myproject/src/providers/core/translate'

在我的服务中,我像下面这样声明fs

declare var require: any;
const fs = require('fs');

我也尝试了以下这种方式来声明它,但没有帮助。
import * as fs from 'fs';

为了让 webpack 忽略 fs,我尝试在我的 webpack.server.config.js 中添加以下内容,但没有成功。
node: {
    fs: 'empty'
}

我也尝试了使用webpack插件,但同样没有成功。

new webpack.IgnorePlugin(/fs/)

但实际上,这可能不是由ng serve使用的配置,但我不知道是否仍然可以使用v6强制执行该配置?

有人有什么想法吗?

更新

如果我将fs声明为any,它可以解决ng serve的问题,但很遗憾,在npm run build:ssr和运行npm run serve后,它在服务器端将无法工作。在服务器端,我将遇到以下错误:

错误:ReferenceError: fs未定义。

p.s.:我的项目遵循https://github.com/angular/universal-starter的结构、配置和依赖项。


1
尝试声明 fs,并声明为 var fs: any; - John Velasquez
很棒,这是一个不错的解决方法,有效地解决了问题,谢谢@JohnVelasquez - 我让你来回答这个问题,然后我会将其标记为解决方案。 - David Dal Busco
当您使用 fs 时,请尝试添加此条件 -> if(typeof window !== 'undefined') - John Velasquez
那样做没有帮助,问题在服务器端,代码也只在服务器端使用(isPlatformServer)。 - David Dal Busco
请查看此答案:https://dev59.com/2q3la4cB1Zd3GeqPSc3I#57506728 - Daniel Danielecki
12个回答

57

由于之前的回答比较旧,可能会有所帮助,这里强调一下Angular9的解决方法,只需在您的package.json中添加以下内容:

"browser": {
    "fs": false,
    "os": false,
    "path": false
  }

这对我来说非常有效。 供参考,我在官方tensorflow/tfjs Github页面这里找到了解决方案。


3
酷毙了。已更新采纳答案并引用了您的参考。 - David Dal Busco
2
Angular 9+的最佳答案 - Daniel Danielecki
2
希望我能为每个错误的解决方案点赞一次。在我的情况下,它解决了错误 ERROR in ./node_modules/foo/foo.js Module not found: Error: Can't resolve 'path' in 'my-app/node_modules/foo,其中 foo 是使用 path 的一个模块。:). 在我的情况下,只需要 "browser": { "path": false } - tresf
检查“browser”字段的规范,以了解它为什么有效(或无效):https://github.com/defunctzombie/package-browser-field-spec - j2L4e
6
修复了构建问题,但我的应用程序现在无法正确加载,出现了“Uncaught ReferenceError: __dirname is not defined at Object.vbkW (index.js:4)”的错误。 - d4rty
1
是的,2022年使用“文件系统”模块并且这个修复程序没有任何作用。有人能够在Angular 14中使其正常工作吗? - Jake_3H

34

2020更新

查看Marc对Angular v9的回答:答案

2019更新

根据@Tahlil的评论,现在已经可以这样做。 对于Angular v8(Ivy编译器),请参见此答案。它在package.json中将特定模块设置为浏览器中不使用。

原始回答

经过几个小时的探讨和收集答案,我得出结论,真正的答案是:

您无法在Angular v6中再使用fs

此外,由于无法再弹出webpack配置,因此无法告诉webpack忽略fs require。

有一个关于此主题的未解决问题:https://github.com/angular/angular-cli/issues/10681

P.S.:我使用fs在服务器端加载翻译内容,我通过遵循@xuhcc的解决方案来克服这个问题,请参见https://github.com/ngx-translate/core/issues/754


原来你是可以的。https://dev59.com/Cek5XIcBkEYKwwoY7eME - Tahlil
我的回答已经超过一年了。我在其中添加了一条评论。 - David Dal Busco

14

如果还有人在寻找答案,这里是我在我的Angular 7应用程序中如何使用require('fs')的方式。或者说,任何其他的Node模块也适用。

版本

Angular CLI: 7.0.4
Node: 10.13.0
OS: win32 x64
"@angular/animations": "~7.0.0",
"@angular/common": "~7.0.0",
"@angular/compiler": "~7.0.0",
"@angular/core": "~7.0.0",
"@angular/forms": "~7.0.0",
"@angular/http": "~7.0.0",
"@angular/platform-browser": "~7.0.0",
"@angular/platform-browser-dynamic": "~7.0.0",
"@angular/router": "~7.0.0",
"@angular-devkit/build-angular": "~0.10.0",
"@angular/cli": "~7.0.4",
"@angular/compiler-cli": "~7.0.0",
"@angular/language-service": "~7.0.0",
"electron": "^3.0.7",
"typescript": "~3.1.1"

1. 安装 @types/node

npm install --save-dev @types/node

2. 修改 tsconfig.json

请注意 "allowSyntheticDefaultImports" 标志,它必须设置为 true。

{
  "compileOnSave": false,
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "module": "es2015",
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5",
    "types": [
      "node"
    ],
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2018",
      "dom"
    ],
    "strict": false
  }
}

3. 要求fs模块

import { Component } from '@angular/core';
import { } from 'electron';
import Fs from 'fs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {

  constructor() {
    //check if platform is electron
    let isElectron: boolean = window && window['process'] && window['process'].type;

    if (isElectron) {
      let fs: typeof Fs = window['require']('fs');
      let app: Electron.App = window['require']('electron').remote;
      console.log(fs, app, window['process']);
    }
  }
}

注意: 文件顶部的导入语句只是用于提供类型信息。变量的值使用 require 来设置。

有关更新,请在此跟踪问题

https://github.com/angular/angular-cli/issues/9827

编辑:

事实证明,如果您的项目具有需要 'fs'、'path'、'child_process' 等的依赖项,则 Angular 编译器将无法编译代码。如已有人建议的那样,要解决这个问题,在您的 polyfills.ts 中添加 (window as any).global = window; 即可。

在我的情况下,我有 chokidarnode-ptyelectron 作为依赖项。这对我有用。


很难在没有任何信息的情况下判断,你使用的是哪个版本的Angular、Electron和Node.js? - Nishkal Kashyap
1
我比之前更接近目标了,但是在尝试使用 window['require'] 时出现了错误 TypeError: window.require 不是一个函数。不确定如何解决这个问题。 - ntgCleaner
@ntgCleaner 试试这个:declare global { interface Window { require: NodeRequire; } }然后,使用 window['require']。如果这是 TypeScript 编译器错误,那么它必须通过这种方式解决。如果这不起作用,请尝试这个:window['require']=eval('require')。然后再使用 window['require'] - Nishkal Kashyap
@NishkalKashyap 经过尝试你提到的方法并进行更多的尝试后,我似乎无法让它正常工作。我正在尝试使用cheerio和request-promise进行一些简单的网络爬虫,但它们都需要使用require。我会继续尝试其他方法。 - ntgCleaner
与 electron 4.1.0,Ionic 5 和 angular 8 完美配合。 - Mr. Ratnadeep
显示剩余3条评论

5
在Angular 8中,您现在可以使用Angular Builders来指定一个web.config.js文件,该文件扩展了由Angular生成的虚拟配置。 此篇博客文章解释得非常清楚。
tldr:
  1. 运行 npm i -D @angular-builders/custom-webpack
  2. 编辑您的angular.json文件architect.servearchitect.build,告诉它使用custom-webpack模块,将webpack.config.js文件与虚拟配置扩展
  3. 创建自定义的webpack.config.js - 在本例中,它应该如下所示:
module.exports = {
    node: {
        fs: 'empty'
      }
};

3

1

接受的答案是正确的;在Angular v6+中不能再使用fs

然而,这个替代构建工具(它是Angular CLI的扩展)允许你针对Electron环境进行定位,并完全访问Electron的功能:

https://github.com/angular-guru/electron-builder


1
我通过添加 "

" 来修复了这个问题。
"types": [
  "node"
]

在 tsconfig.app.json 中。

0

我正在一个 Angular CLI monorepo 中运行一个 Angular 应用程序,通过 Nx schematics 的帮助设置。我正在共享 lib 目录中的代码

当尝试在 Angular 应用程序中使用来自共享 lib 的 Typescript 枚举时,我遇到了以下错误:

关键依赖项:依赖项的请求是表达式

无法解析 'fs'

错误堆栈包括:

这件事很奇怪,因为表面上看来枚举类型的包含与 type-graphql 没有任何关系。

问题实际上与 type-graphql 架构和 Typescript 枚举在同一 lib 中定义有关。将 Enums 提取到它们自己的 lib 中解决了问题。我不清楚错误发生的原因,但无论如何,这个解决方案起作用了。

编辑

因此,问题是根据 this nx issuethis type-graphql issue,在某个时刻,将 TypeGraphQL 中的内容包括进来会尝试将整个 TypeGraphQL 捆绑到浏览器应用程序中(@Input() decorator 似乎也是其中之一)。

如果你想在前端包含 TypeGraphQL 类,解决方案是 update the webpack config。在 AngularCLI 应用程序中这样做 涉及相当多的步骤


0

你也可以通过这种方式声明fsdeclare var fs: any;


1
实际上,不幸的是,它并没有完全解决问题。这可以解决 ng serve 的问题,但如果我构建我的项目,运行 npm run build:ssr,然后运行 npm run serve,我将在服务器端面临错误 fs is not defined :( - David Dal Busco

0

如果您在规范文件中导入了jasmine以避免tslint错误,您应该执行以下操作:

  1. 从规范文件中删除import jasmine;
  2. tsconfig.json中添加jasmine
...
...
"compilerOptions": {
  ...
  ...
  "types": [
      "webpack-env",
      "jasmine"
  ]
  ...
  ...
}
...
...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接