-
Notifications
You must be signed in to change notification settings - Fork 394
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
SWC Support #1549
Comments
@kamilmysliwiec I would actually be interested in adding this support and maintaining it. As an anecdote I just swapped my ogma repo to use swc and uvu for tests and went from 40 seconds down 10 is running each package through nx otherwise 9 seconds down to 800ms. Adding in decorator and path support was a single file config. We could make a flag on new repos to use swc and generate the Let me know if you'd like me to start working on this, or if you think it should be outside the nest CLI. |
I'd be in as well! I experimented with a repository already (dev server, build and running jest tests via I haven't tested support in monorepos, though. there were some great answers in the previous thread (originally about esbuild) here: TLDR; There would be several ways to solve this:
I'd be really interested to help exploring more possibilities to use swc with nest :) EDIT: |
Sounds great @jmcdo29! AFAIR
@manuschillerdev CLI plugins extensively use TypeScript's type checker to guess types while parsing ts files and this doesn't seem to be feasible with SWC AST (type-checker is what actually slows down the |
If the type checker is a must-have requirement of the CLI plugins, then tsc AST compat seems like the only option, but with the type-checking being the largest bottleneck of
Is that because the SWC AST has already had types removed? Or do you mean you actually need to use type inference? E.g. I'm thinking something like the Swagger cli plugin just needs the types in the AST, not necessarily inferred? Also worth mentioning that SWC is developing its own type-checker as well, though will probably not be ready anytime soon. That said, may be worth holding out for. |
Perhaps we could run some benchmarks just to see if there's at least a minor performance improvement (?)
One thing to keep in mind: even if they implement their own type-checker, I don't think we'll be capable of maintaining 2 versions of the plugin alongside this package and the whole ecosystem (the maintenance cost is simply too high in this case). |
@kamilmysliwiec the only way to use swc in combination with webpack is Example webpack-config with HMR (I didn't find HMR to work really reliable with and without swc, but didn't spend too much time with it): npm task: // webpack-hmr.config.js
const nodeExternals = require('webpack-node-externals');
const { RunScriptWebpackPlugin } = require('run-script-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
module.exports = function (options, webpack) {
options.module.rules.forEach((rule) => {
rule.use?.forEach((use) => {
if (use.loader === 'ts-loader') {
use.loader = 'swc-loader';
delete use.options;
}
});
});
options.plugins = options.plugins.filter(
(plugin) => !(plugin instanceof ForkTsCheckerWebpackPlugin),
);
return {
...options,
entry: ['webpack/hot/poll?100', options.entry],
externals: [
nodeExternals({
allowlist: ['webpack/hot/poll?100'],
}),
],
plugins: [
...options.plugins,
new webpack.HotModuleReplacementPlugin(),
new webpack.WatchIgnorePlugin({
paths: [/\.js$/, /\.d\.ts$/],
}),
new RunScriptWebpackPlugin({ name: options.output.filename }),
],
};
};
{
"sourceMaps": "inline",
"module": {
"type": "commonjs",
"strict": true
},
"jsc": {
"target": "es2020",
"parser": {
"syntax": "typescript",
"decorators": true
},
"transform": {
"legacyDecorator": true,
"decoratorMetadata": true
},
"keepClassNames": true
}
}
@jackel119 @kamilmysliwiec |
@jackel119 @kamilmysliwiec Custom Types are also part of the AST. |
Is there anyone working in such feature? I might be interested and I could also help with the implementation following maybe @manuschillerdev approach. I believe the future (ironically) of JS/TS tooling would be in using other compiled languages that can give us better performance on the tooling side, so migrating to those give us great benefits over actual JS only tooling. |
I played around with the swc-loader the other day, and while it mostly worked, it does fail on swagger-cli-plugin and the graphql-cli-plugin. The AST differs and we'd need to end up supporting both Typescript's direct AST and SWC's AST which might be more of a burden then we are expecting to take on. If you aren't using those plugins, you should be able to drop the swc-loader into a webpack.config.js file and be on your merry way, but those plugins do seem to cause issues. Of course, YMMV, but I'm not sure how feasible it will be, at least right now, to support swc. It's a shame, but it's a part of modern tooling y'know? |
Regarding cli plugins, the current implementation indeed uses a typescript type checker to determine types. And this is a problem even without SWC context. So it would be a good step for the nestjs to rewrite those plugins to not use Typechecker at all and make it more opinionated on the way how users should write code. Then it would be possible to rewrite them to SWC in rust. Some examples: You don't need a TypeChecker to transform this code: import {WeekDay} from "./week-day.model.ts";
export class PoiWorkingHoursEntry {
public readonly days: WeekDay[];
} But need to transform this code, because of Type Alias and some magic with null: import {WeekDay} from "./week-day.model.ts";
type MyTypeAlias = WeekDay | null;
export class PoiWorkingHoursEntry {
public readonly days: MyTypeAlias[];
} Actually, transformer could produce something like this: // pseudocode, actual transformer produce diffferent code
type MyTypeAlias = WeekDay | null;
@Field(() => {
if (typeof MyTypeAlias === void 0) {
throw new Error("`PoiWorkingHoursEntry.days` has unsupported type. You probably passed a typealias instead of real type.")
}
return MyTypeAlias;
})
public readonly days: MyTypeAlias[]; But instead, current transformer uses TypeChecker and trying to resolve all possible ways how user can write code in TS. I would like to participate in this, but first it should be discussed with @kamilmysliwiec and formulated development / migration plan. |
This part of the code doesn't work. options.plugins = options.plugins.filter(
(plugin) => !(plugin instanceof ForkTsCheckerWebpackPlugin),
); i change to 👇 , and it work perfect. options.plugins = options.plugins.filter(
(plugin) =>
Object.getPrototypeOf(plugin).constructor.name !==
'ForkTsCheckerWebpackPlugin'
); |
my .swcrc file is: {
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": true,
"module": {
"type": "commonjs",
"strict": true
},
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true
},
"transform": {
"legacyDecorator": true,
"decoratorMetadata": true
},
"keepClassNames": true,
"baseUrl": "./",
"paths": {
"@/*": [
"src/*"
],
"src/*": [
"src/*"
]
}
},
"minify": false
} and the build script is: {
"scripts": {
"start:dev": "node dist/main",
"build:swc": "swc --ignore \"**/*.spec.ts,src/hmr.ts\" --delete-dir-on-start --out-dir dist/ src/",
"dev:swc": "npm run build:swc && npm run start:dev",
"start:swc": "cross-env NODE_ENV=development npx nodemon --quiet --watch \"src/**\" --ext \"ts,json\" --ignore \"src/**/*.spec.ts\" --exec npm run dev:swc"}
} |
@kamilmysliwiec i can rewrite GraphQL plugin to SWC. Please DM me if you're interested in that. Also, this phrase in the docs:
Is incorrect. SWC plays well with circular dependencies. The input is wrong. SWC just strictly followed standard, instead of relying on quirks as typescript and babel do. And this statement also appliable to GraphQL nestjs integration. It also may have circular issues related to emitDecoratorMetadata. |
Contributions are more than welcome |
I think it would be even more interesting to give rspack a try https://www.rspack.dev/ as it's a full webpack compatible bundler that uses swc under the hood. Same API but with the speed of swc. Even a lot faster than webpack + swc: So you could provide the same feature set including HMR with the speed improvement and hopefully no big refactoring. Should be more less a drop in replacement. |
Rspack's default configuration should be sufficient for NestJS projects. Would you like to create a PR to the docs, adding the Rspack recipe? |
@kamilmysliwiec sure. I can do that! What's against swapping it with webpack by default? |
It is not yet stable |
@lukasholzer Any progress on the Rspack recipe--it would be absolutely awesome(!)--any unforeseen obstacles? |
Worth mentioning here that currently SWC has an issue with Path Aliases from outside the Root Dir |
Would like to see the instruction for utilizing vite HMR and vite build. |
https://github.com/web-infra-dev/rspack/tree/main/examples/nestjs you can use rspack build nestjs app now. |
Kamil shared a sneak peek of SWC integrated within the Nest.js CLI on LinkedIn: https://www.linkedin.com/posts/kamil-mysliwiec-992bbb105_nodejs-nestjs-typescript-activity-7069957494017523713-u6kn?utm_source=share&utm_medium=member_desktop One of his comments:
It will also be integrated with |
Is there an existing issue that is already proposing this?
Is your feature request related to a problem? Please describe it
Build times for large projects can be quite slow, which makes both local development and CI deploy times slow.
For a small project of mine (around 6k lines),
tsc
takes 5.2 seconds to build.swc
on the other hand takes 0.38 seconds - that's over a 10x improvement.Related to #731 in the sense that this is a request/discussion for a faster build system support, but as ESBuild are not going to support
emitDecoratorMetadata
anytime soon but SWC already does, I think it makes more sense to push for that.Describe the solution you'd like
Allow
nest build
to useswc
via some flag e.g.nest build --swc
.Teachability, documentation, adoption, migration strategy
The discussion in #731 is making it evident that we are much closer to being able to have SWC build NestJS projects - the boilerplate NestJS app already runs fine from SWC builds, there are just some kinks/edge cases that need to be tracked i.e. CLI plugins that require AST transformations, certain decorators, etc.
I understand a lot of the work that needs to be done is not necessarily on Nest's side, but rather on SWC's side to fix it's issues. Still, I think it's useful to have an issue dedicated specifically for SWC rather than hijacking a closed one about esbuild.
What is the motivation / use case for changing the behavior?
Speeeeed.
The text was updated successfully, but these errors were encountered: