问题
对于想要复制所有 JSON 文件的人来说,在 TypeScript 中真的很难。即使使用"resolveJsonModule": true,tsc 也只会复制.json 直接由import 引用的文件。
这里是一些示例代码,它想要做一个动态运行时require()。这只有在所有 JSON 文件都已复制到 dist/ 文件夹中时才有效,这是 tsc refuses 要做的。
// Works
import * as config from './config.default.json';
const env = process.env.NODE_ENV || 'development';
const envConfigFile = `./config.${env}.json`;
// Does not work, because the file was not copied over
if (fs.existsSync(envConfigFile)) {
const envConfig = require(envConfigFile);
Object.assign(config, envConfig);
}
方案一:将 json 文件放在 src 树之外(推荐)
假设您有 /src/ 和 /dist/ 文件夹,您可以将 JSON 文件保存在项目的 / 文件夹中。然后位于/src/config/load-config.ts 的脚本可以在运行时执行此操作:
const envConfig = require(`../../config.${env}.json`);
// Or you could read manually without using require
const envConfigFile = path.join(__dirname, '..', '..', `config.${env}.json`);
const envConfig = JSON.parse(fs.readFileSync(envConfigFile, 'utf-8'));
这是最简单的解决方案。您只需要确保必要的配置文件将在生产环境中到位。
其余的解决方案将处理您确实希望将配置文件保留在 src/ 文件夹中并让它们出现在您的 dist/ 文件夹中的情况。
解决方案 2:导入所有可能的文件
对于上面的例子,我们可以这样做:
import * as config from './config.default.json';
import * as testingConfig from './config.testing.json';
import * as stagingConfig from './config.staging.json';
import * as productionConfig from './config.production.json';
这应该会导致指定的 json 文件被复制到 dist/ 文件夹中,所以我们的 require() 现在应该可以工作了。
缺点:如果有人想添加一个新的.json 文件,那么他们还必须添加一个新的导入行。
方案3:单独复制json文件(推荐)
您可以在tsc 完成后添加cpy-cli 或copyfiles 步骤to your build process 将所有.json 文件复制到dist/ 文件夹中。
这假设您使用 npm run build 或类似的东西进行构建。
例如:
$ npm install --save-dev cpy-cli
// To copy just the json files, add this to package.json
"postbuild": "cpy --cwd=src --parents '**/*.json' ../dist/",
// Or to copy everything except TypeScript files
"postbuild": "cpy --cwd=src --parents '**/*' '!**/*.ts' ../dist/",
现在npm run build 应该运行tsc,然后运行cpy。
缺点:需要额外的devDependency。您必须将此作为构建过程的一部分。
方案四:使用js文件代替json文件
或者,不要使用.json 文件。将它们移动到.js 文件中,并在您的tsconfig.json 中启用"allowJs": true。然后tsc 将为您复制文件。
您的新 .js 文件需要如下所示:module.exports = { ... };
我发现了这个想法recommended here。
注意:为了启用"allowJs": true,您可能还需要添加"esModuleInterop": true 和"declaration": false,甚至可能需要添加"skipLibCheck": true。这取决于您现有的设置。
还有另一个问题(抱歉我没有测试这个):
- 如果
tsc 的配置文件并非全部被其他文件静态引用,它们会转译它们吗?您的文件或其文件夹可能需要在 tsconfig.json 的 files 或 include 选项中明确引用。
解决方案5:使用ts文件而不是json文件
听起来很简单,但仍有一些问题需要考虑:
-
您的配置文件现在看起来像这样:const config = { ... }; export default config;
-
请参阅上面关于 files / include 选项的说明。
-
如果您在运行时动态加载配置文件,请不要忘记它们已被转译为 .js 文件。所以不要去尝试require().ts文件,因为它们不会在那里!
-
如果有人想更改配置文件,他们应该进行全新的tsc 构建。他们可以修改dist 文件夹中的转译.js 文件,但应该避免这种情况,因为这些更改可能会被未来的构建覆盖。
测试
在尝试此操作时,请确保在构建之间清除您的dist/ 文件夹和tsconfig.tsbuildinfo 文件,以便正确测试该过程。 p>
(tsc 并不总是清理dist/ 文件夹,有时它只是向其中添加新文件。因此,如果您不删除它们,早期实验遗留下来的旧文件可能会产生误导性结果!)