102 lines
3.1 KiB
TypeScript
102 lines
3.1 KiB
TypeScript
import fs from "fs"
|
|
import { extname } from "path"
|
|
import * as babel from "@babel/core"
|
|
import type * as esbuild from "esbuild"
|
|
import { fileName } from "./babel-filename"
|
|
import { dynamicImport } from "./babel-dynamic-import"
|
|
import { inlineCSSVariables } from "./babel-inline-css-vars"
|
|
import { componentName } from "./babel-component-name"
|
|
// import { whyDidYouRender } from "./babel-why-did-you-render";
|
|
// import constantElement from "./babel-constant-element";
|
|
|
|
const __PROD__ = process.env.NODE_ENV === "production"
|
|
|
|
export type BabelPlugin<T = unknown> = (
|
|
Babel: typeof babel,
|
|
) => babel.PluginObj<T & babel.PluginPass>
|
|
|
|
export interface BabelPluginData {
|
|
path: string
|
|
}
|
|
|
|
export const babelPlugin = (extraPlugins: babel.PluginItem[] = []): esbuild.Plugin => ({
|
|
name: "babel",
|
|
setup(build) {
|
|
function* getBabelPlugins(
|
|
path: string,
|
|
content: string,
|
|
): Generator<babel.PluginItem, void, unknown> {
|
|
const hasFileName = content.includes("__filename")
|
|
const hasDirName = content.includes("__dirname")
|
|
if (hasFileName || hasDirName) {
|
|
yield fileName({ hasFileName, hasDirName, path })
|
|
}
|
|
if (!__PROD__ && /<\w/.test(content)) {
|
|
yield componentName()
|
|
}
|
|
// if (!__PROD__ && content.includes("use")) {
|
|
// yield whyDidYouRender({
|
|
// hookName: "useWhyDidYouUpdate",
|
|
// hookPath: resolve(__dirname, "../../src/shared/hooks/useWhy.ts"),
|
|
// ignoredHooks: ["useTreeContext"],
|
|
// });
|
|
// }
|
|
if (content.includes("vars.") || content.includes("token.")) {
|
|
yield inlineCSSVariables()
|
|
}
|
|
if (content.includes("await import(`")) {
|
|
yield dynamicImport(path)
|
|
}
|
|
if (content.includes('.macro"') || content.includes("/macro")) {
|
|
yield ["babel-plugin-macros", { typeGraphQL: { useParameterDecorator: true } }]
|
|
}
|
|
if (content.includes("@emotion")) {
|
|
yield [require("@emotion/babel-plugin"), { sourceMap: false }]
|
|
}
|
|
|
|
if (__PROD__ && content.includes("gql`")) {
|
|
yield [require("babel-plugin-transform-minify-gql-template-literals")]
|
|
}
|
|
}
|
|
|
|
build.onLoad({ filter: /\.tsx?$/ }, args => {
|
|
if (args.path.includes("node_modules/")) {
|
|
return null
|
|
}
|
|
|
|
const { path } = args
|
|
const file = fs.readFileSync(path, "utf-8")
|
|
|
|
const plugins: babel.PluginItem[] = Array.from(getBabelPlugins(path, file)).concat(
|
|
extraPlugins,
|
|
)
|
|
|
|
let code = file
|
|
const pluginData: BabelPluginData = { path }
|
|
|
|
if (plugins.length) {
|
|
const res = babel.transformSync(file, {
|
|
filename: path,
|
|
babelrc: false,
|
|
configFile: false,
|
|
parserOpts: {
|
|
plugins: ["typescript", "decorators-legacy", "jsx", "importAssertions"],
|
|
},
|
|
generatorOpts: { decoratorsBeforeExport: true },
|
|
plugins,
|
|
})!
|
|
|
|
code = res.code!
|
|
} else {
|
|
return null
|
|
}
|
|
|
|
return {
|
|
contents: code,
|
|
loader: extname(path).slice(1) as any,
|
|
pluginData,
|
|
}
|
|
})
|
|
},
|
|
})
|