Webpack:未导入模块的 ModuleNotFoundError

时间:2021-06-29 20:57:37

标签: javascript node.js heroku webpack next.js

问题

我的项目由一个 yarn monorepo 组成,其中,在各种包中,有一个 NextJS 应用程序和一个配置包(也与服务器和 react-native 应用程序共享)。在配置模块中,如果环境是生产环境,我做的是导出生产密钥,而如果项目正在开发中,则导出开发密钥。

import { merge } from "lodash";
import { IConfig, RecursivePartial } from "./interfaces";
import { defaultKeys } from "./default.keys";
import { existsSync } from "fs";

const secretKeys: RecursivePartial<IConfig> = (function (env) {
  switch (env) {
    case "production":
      return require("./production.keys").productionKeys;

    default:
      try {
        if (!existsSync("./development.keys")) {
          return require("./production.keys").productionKeys;
        } else {
          return require("./development.keys").developmentKeys;
        }
      } catch (e) {
      }
  }
})(process.env.NODE_ENV);

export const keys = merge(defaultKeys, secretKeys) as IConfig;

当然,开发配置文件包含在 .gitignore 文件中,因此在生产过程中不存在。

这一直都很完美(与服务器和移动应用程序一起使用),事实上,如果 development.keys 文件存在,则从来不需要检查 fs 模块(检查我稍后添加的内容)。

不过,我最近在项目中添加了一个 NextJs 应用程序。我在开发过程中没有遇到任何问题,但是当我尝试在 Heroku 上部署应用程序时,我遇到了这个错误:

ModuleNotFoundError: Module not found: Error: Can't resolve './development.keys' in '/tmp/build_43d652bc/packages/config/dist/keys'

我做了什么

最初,我认为是环境变量的问题,并且在生产中错误地需要开发文件。 但是,后来我意识到这不是问题。事实上,即使将用于开发的配置文件的导入放置在代码的任何位置,即使在返回之后,错误也会继续发生。

import { merge } from "lodash";
import { IConfig, RecursivePartial } from "./interfaces";
import { defaultKeys } from "./default.keys";
import { existsSync } from "fs";

const secretKeys: RecursivePartial<IConfig> = (function (env) {
  switch (env) {
    case "production":
      return require("./production.keys").productionKeys;

    default:
      try {
           if (!existsSync("./development.keys")) {
             return require("./production.keys").productionKeys; // <-------
        } else {
          return require("./production.keys").productionKeys; // <-------
        }

        require("./development.keys").developmentKeys;  // <------- This line should not be executed
      } catch (e) {
        return require("./production.keys").productionKeys;
      }
  }
})(process.env.NODE_ENV);

export const keys = merge(defaultKeys, secretKeys) as IConfig;

就好像在构建过程中,nextjs(或者可能是 webpack)控制了所有的导入,没有遵循代码的“流程”。

我希望有人告诉我我错在哪里,因为目前我被卡住了。谢谢!

更新

感谢 this 讨论的想法,我更改了我的文件,现在看起来像这样:

const getConfigPath = (env?: string): string => {
  console.log(env);
  if (env === "production") return "production.keys";
  else return "development.keys";
};

const secretKeys: RecursivePartial<IConfig> = require("./" +
  getConfigPath(process.env.NODE_ENV)).keys;

export const keys = merge(defaultKeys, secretKeys) as IConfig;

但是,现在我遇到了另一个 webpack 错误:

Module parse failed: Unexpected token (2:7)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| import { IConfig, RecursivePartial } from "../interfaces";
> export declare const keys: RecursivePartial<IConfig>;

就好像 webpack 不识别 typescript 生成的声明文件一样。但是,该错误是新的,我从未遇到过。我相信这是由于链接讨论中指出的 webpack 行为所致。

我相信一些帮助,因为我对 webpack 知之甚少

编辑

这是我的 next.config.js:

const path = require("path");

 module.exports = {
    distDir: '../../.next',
    sassOptions: {
        includePaths: [path.join(__dirname, 'styles')],
        prependData: `@import "variables.module.scss";`
    },
    webpack: (config, { isServer }) => {
      if (!isServer) {
        config.resolve.fallback.fs = false;
      }
      return config;
    },
};   

基本上它们是默认配置。我唯一改变的是构建路径,我创建了一个 sass 文件全局,我暂时添加了一段代码以允许使用 fs 模块,但是正如你在上面看到的,我没有使用它更多的。所以我可以去掉这个配置。

1 个答案:

答案 0 :(得分:1)

您需要在 next.config.js 中配置打字稿的加载程序

npm install || yarn add awesome-typescript-loader

module.exports = {

    distDir: '../../.next',
    sassOptions: {
        includePaths: [path.join(__dirname, 'styles')],
        prependData: `@import "variables.module.scss";`
    },

    webpack: (config, options) => {

      const { dir, defaultLoaders, isServer } = options;

      if (!isServer) {
        config.resolve.fallback.fs = false;
       }
    
      config.pageExtensions.push(".ts", ".tsx");
    
      config.resolve.extensions.push(".ts", ".tsx");
    
      config.module.rules.push({
        test: /\.tsx?$/,
        include: [dir],
        exclude: /node_modules/,
        use: [
          defaultLoaders.babel,
          {
           loader: "awesome-typescript-loader",,
          },
        ],
     });
    
    return config;
  }
}
相关问题