Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 支持ts-checker #956

Merged
merged 11 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,13 @@ function App() {
}
```

## forkTsChecker
ctts marked this conversation as resolved.
Show resolved Hide resolved

- 类型:`boolean`
- 默认值:`false`

是否开启构建时 ts 校验。

## umd

- 类型:`false | string`
Expand All @@ -444,3 +451,4 @@ function App() {
- 默认值:`true`

是否在 mode 为 development 时将构建结果写入磁盘。

9 changes: 9 additions & 0 deletions packages/bundler-okam/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const assert = require('assert');
const { createProxy, createHttpsServer } = require('@umijs/bundler-utils');
const lodash = require('lodash');
const chalk = require('chalk');
const { ForkTsChecker } = require('./plugins/fork-ts-checker/index');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const { ForkTsChecker } = require('./plugins/fork-ts-checker/index');
const { ForkTsChecker } = require('./fork-ts-checker/index');

不要 plugins 目录,因为实际上 bundler-okam 层没有 plugin 机制。

const {
createProxyMiddleware,
} = require('@umijs/bundler-utils/compiled/http-proxy-middleware');
Expand Down Expand Up @@ -99,6 +100,12 @@ exports.build = async function (opts) {
throw err;
}

// 后置 ts 校验,不影响打包速度
if (!!okamConfig.forkTsChecker) {
ctts marked this conversation as resolved.
Show resolved Hide resolved
const forkTypeChecker = new ForkTsChecker(cwd);
forkTypeChecker.runTypeCheck();
}

const statsJsonPath = path.join(cwd, 'dist', 'stats.json');
const statsJson = JSON.parse(fs.readFileSync(statsJsonPath, 'utf-8'));

Expand Down Expand Up @@ -467,6 +474,7 @@ async function getOkamConfig(opts) {
externals,
copy = [],
clean,
forkTsChecker,
} = opts.config;
const outputPath = path.join(opts.cwd, 'dist');
// TODO:
Expand Down Expand Up @@ -595,6 +603,7 @@ async function getOkamConfig(opts) {
flexBugs: true,
react: opts.react || {},
emotion,
forkTsChecker,
...(opts.disableCopy ? { copy: [] } : { copy: ['public'].concat(copy) }),
};

Expand Down
30 changes: 30 additions & 0 deletions packages/bundler-okam/plugins/fork-ts-checker/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const { fork } = require('child_process');
const path = require('path');
const { TypeChecker } = require('./ts-checker');

class ForkTsChecker {
constructor(projectRoot) {
this.projectRoot = projectRoot;
}
async runTypeCheck() {
const typeChecker = new TypeChecker(projectRoot);
await typeChecker.check();
}

runTypeCheckInChildProcess() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

没有走子进程的这个逻辑吗?

const workerScript = path.join(__dirname, 'child_process_fork.js');
const child = fork(workerScript, [projectRoot], {
stdio: 'inherit',
});

child.on('exit', (code) => {
if (code === 0) {
console.log('Type checking completed successfully.');
} else {
console.error('Type checking failed.');
}
});
}
}

module.exports = { ForkTsChecker };
97 changes: 97 additions & 0 deletions packages/bundler-okam/plugins/fork-ts-checker/ts-checker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
const ts = require('typescript');
const path = require('path');
const fs = require('fs').promises;

class TypeChecker {
constructor(projectRoot) {
this.projectRoot = projectRoot;
}

async check() {
try {
const configPath = ts.findConfigFile(
this.projectRoot,
ts.sys.fileExists,
'tsconfig.json',
);
if (!configPath) {
console.error(
'Could not find a valid "tsconfig.json" file in the project root:',
this.projectRoot,
);
return;
}
let configFileText = '';
try {
configFileText = await fs.readFile(configPath, 'utf8');
} catch (readError) {
console.error(
`Error reading the "tsconfig.json" file at ${configPath}:`,
readError,
);
return;
}
const configFile = ts.parseConfigFileTextToJson(
configPath,
configFileText,
);
if (configFile.error) {
console.error('Error parsing "tsconfig.json" file:', configFile.error);
return;
}
let parsedCommandLine;
try {
parsedCommandLine = ts.parseJsonConfigFileContent(
configFile.config,
ts.sys,
path.dirname(configPath),
);
} catch (parseError) {
console.error(
'Error parsing the configuration from "tsconfig.json":',
parseError,
);
return;
}
let program;
try {
program = ts.createProgram({
rootNames: parsedCommandLine.fileNames,
options: { ...parsedCommandLine.options, noEmit: true },
});
} catch (programError) {
console.error('Error creating the TypeScript program:', programError);
return;
}
const diagnostics = ts.getPreEmitDiagnostics(program);
if (diagnostics.length > 0) {
diagnostics.forEach((diagnostic) => {
const message = ts.flattenDiagnosticMessageText(
diagnostic.messageText,
'\n',
);
if (diagnostic.file && typeof diagnostic.start === 'number') {
const { line, character } =
diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
console.error(
`${diagnostic.file.fileName} (${line + 1}, ${
character + 1
}): ${message}`,
);
} else {
console.error(message);
}
});
} else {
console.log('No type errors found.');
}
} catch (error) {
console.error(
'An unexpected error occurred during type checking:',
error,
);
}
}
}

module.exports = { TypeChecker };
10 changes: 10 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading