const babel = require("@babel/core");
const path = require("path");
const fs = require("fs");
const resolver = require("enhanced-resolve");
const root = path.resolve(__dirname, "../ant-design");
const entryDir = path.resolve(root, "./components");
const entryFile = "index.tsx";
const resolve = resolver.create.sync({
extensions: [
".web.tsx",
".web.ts",
".web.jsx",
".web.js",
".ts",
".tsx",
".js",
".jsx",
".json",
],
fileSystem: fs,
alias: {
"@ant-design/tools": path.resolve(__dirname, "../ant-design"),
},
});
function getDirFromAbsolutePath(p) {
return path.dirname(p);
}
function getFileFromAbsolutePath(p) {
return p.split("/").pop();
}
function isNotJsFile(file) {
return !(
file.endsWith(".js") ||
file.endsWith(".ts") ||
file.endsWith(".jsx") ||
file.endsWith(".tsx")
);
}
function dfs(dir, file, set, callback) {
if (isNotJsFile(file)) {
return;
}
const target = path.resolve(dir, file);
if (set.has(target)) {
return;
} else {
set.add(target);
}
if (set.size % 100 == 0) {
console.log(
`Already processed ${set.size} files, now is deal with ${target}`
);
}
const code = fs.readFileSync(target).toString("utf-8");
const nodeHadRemoveTS = babel.transformSync(code, {
presets: ["@babel/preset-typescript"],
plugins: [
[
"@babel/plugin-proposal-decorators",
{
version: "2021-12",
},
],
],
ast: true,
filename: target,
configFile: false,
sourceMaps: false,
code: false,
highlightCode: false,
comments: false,
});
if (!nodeHadRemoveTS.ast) {
return;
}
babel.traverse(nodeHadRemoveTS.ast, {
enter(p) {
let value = "";
if (p.isImportDeclaration()) {
value = p.node.source.value;
} else if (p.isExportNamedDeclaration()) {
if (!p.node.source) {
return;
}
value = p.node.source.value;
} else if (p.isCallExpression() && p.node.callee.name === "require") {
if (typeof p.node.arguments?.[0].value === "string") {
value = p.node.arguments[0].value;
} else {
console.log(target);
}
} else if (p.isCallExpression() && p.node.callee?.type === "Import") {
if (typeof p.node.arguments?.[0].value === "string") {
value = p.node.arguments[0].value;
} else {
console.log(target);
}
} else {
return;
}
if (value === "") {
return;
}
try {
const next = resolve(dir, value);
callback(dir, value);
dfs(
getDirFromAbsolutePath(next),
getFileFromAbsolutePath(next),
set,
callback
);
} catch (err) {
console.log(
`[IGNORED FAILED] resolve ${value} in ${dir} failed, and ignored it.`
);
}
},
});
}
function run(callback) {
dfs(entryDir, entryFile, new Set(), callback);
}
const HEADER = `// DO NOT EDIT THIS FILE.
// It is auto-generated by <project>/bench/scripts/generator-rs-benchmark.js
`;
function generatorRsBenchmark() {
let content =
HEADER +
`
#![feature(test)]
extern crate test;
#[cfg(test)]
mod bench_test {
use nodejs_resolver::{Resolver, Options, ResolveResult, Resource, RResult};
use std::path::PathBuf;
use test::Bencher;
// use std::time::Instant;
fn is_ok(result: RResult<ResolveResult<Resource>>) {
assert!(result.is_ok())
}
#[bench]
fn ant_design_bench(b: &mut Bencher) {
b.iter(|| {
let resolver = Resolver::new(Options {
extensions: vec![
".web.tsx",
".web.ts",
".web.jsx",
".web.js",
".ts",
".tsx",
".js",
".jsx",
".json",
].into_iter().map(String::from).collect(),
..Default::default()
});
// let start = Instant::now();
`;
run(function (dir, file) {
content += `
is_ok(resolver.resolve(
&PathBuf::from("${dir}"),
"${file}",
));
`;
});
content += `
// println!("time cost: {:?} ms", start.elapsed().as_millis());// ms
});
}
}\n`;
console.log("length", content.length);
const rsFileStoredPath = path.resolve(__dirname, "../../tests/bench.rs");
fs.writeFileSync(rsFileStoredPath, content);
}
function generatorEnhanceResolveBenchmark() {
let content =
HEADER +
`
console.time('bench');
const path = require('path');
const { ResolverFactory } = require("enhanced-resolve");
const Benchmark = require('benchmark');
const root = path.resolve(__dirname, "./ant-design");
const resolver = ResolverFactory.createResolver({
extensions: [
'.web.tsx',
'.web.ts',
'.web.jsx',
'.web.js',
'.ts',
'.tsx',
'.js',
'.jsx',
'.json',
],
fileSystem: require('fs'),
alias: {
"@ant-design/tools" : path.resolve(__dirname, '../ant-design'),
},
})
async function resolve(dir, file) {
return new Promise(res => {
resolver.resolve({}, dir, file, {}, (_error, _result) => {
res(undefined)
})
})
}
async function run() {
const tasks = [];
`;
run(function (dir, file) {
content += `tasks.push(resolve('${dir}', '${file}'));\n`;
});
content += `
await Promise.all(tasks);
};
// const suite = new Benchmark.Suite();
// suite
// .add("EnhancedResolve", run)
// .on('cycle', function(event) {
// console.log(String(event.target));
// })
// .run();
run().then(() => {
console.timeEnd('bench');
});
`;
console.log("length", content.length);
const jsFileStoredPath = path.resolve(__dirname, "../enhanceResolve.js");
fs.writeFileSync(jsFileStoredPath, content);
}
function generatorESBuildResolveBenchMark() {
let content =
HEADER +
`
const path = require('path');
const { build } = require('esbuild');
const Benchmark = require('benchmark');
const suite = new Benchmark.Suite();
async function run() {
await build({
stdin: {
contents: '',
},
write: false,
bundle: true,
treeShaking: false,
ignoreAnnotations: true,
platform: 'node',
plugins: [{
name: 'resolve',
setup(build) {
build.onStart(async () => {
console.time('bench')
const tasks = [];
`;
run(function (dir, file) {
content += `tasks.push(build.resolve('${file}', { resolveDir: '${dir}', kind: 'import-statement' } ));\n`;
});
content += `
await Promise.all(tasks);
console.timeEnd('bench')
})
},
}],
})
};
run();
// suite
// .add("ESBuildResolve", run)
// .on('cycle', function(event) {
// console.log(String(event.target));
// })
// .run({ 'async': true });
`;
console.log("length", content.length);
const jsFileStoredPath = path.resolve(__dirname, "../esbuildResolve.js");
fs.writeFileSync(jsFileStoredPath, content);
}
function generatorESBuildNativeResolveBenchMark() {
let content =
HEADER +
`
package main
import (
"github.com/evanw/esbuild/pkg/api"
)
func main() {
api.Build(api.BuildOptions{
Stdin: &api.StdinOptions{
Contents: "",
},
Write: false,
TreeShaking: api.TreeShakingFalse,
Bundle: true,
IgnoreAnnotations: true,
Platform: api.PlatformNode,
Plugins: []api.Plugin{{
Name: "resolve",
Setup: func(build api.PluginBuild) {
build.OnStart(func() (api.OnStartResult, error) {
`;
run(function (dir, file) {
content += `build.Resolve("${file}", api.ResolveOptions{ ResolveDir: "${dir}"})\n`;
});
content += `
return api.OnStartResult{}, nil
})
},
},
},
})
}
`;
console.log("length", content.length);
const goFileStoredPath = path.resolve(
__dirname,
"../esbuildResolve_native.go"
);
fs.writeFileSync(goFileStoredPath, content);
}
if (process.argv[2] === "rs") {
generatorRsBenchmark();
} else if (process.argv[2] === "esbuild") {
generatorESBuildResolveBenchMark();
} else if (process.argv[2] === "enhanced") {
generatorEnhanceResolveBenchmark();
} else if (process.argv[2] === "esbuild_native") {
generatorESBuildNativeResolveBenchMark();
const cp = require("child_process");
cp.spawnSync("go mod init esbuildResolve_native");
cp.spawnSync("go get github.com/evanw/esbuild/pkg/api");
} else {
throw Error("Input the correct argument");
}