问题
我的项目由一个 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 模块,但是正如你在上面看到的,我没有使用它更多的。所以我可以去掉这个配置。
答案 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;
}
}