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

Add civet unplugin #632

Merged
merged 15 commits into from
Aug 31, 2023
Merged

Add civet unplugin #632

merged 15 commits into from
Aug 31, 2023

Conversation

Mokshit06
Copy link
Contributor

This PR adds an unplugin for simultaneously create vite, rollup, esbuild, rspack and esbuild transformer for civet.

@Mokshit06 Mokshit06 temporarily deployed to build August 15, 2023 15:39 — with GitHub Actions Inactive
Copy link
Contributor

@STRd6 STRd6 left a comment

Choose a reason for hiding this comment

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

Looks good!

Some possible areas for future work:

  • Update the Civet package build step so that people won't need to install a separate package and will be able to import any plugin directly.
  • Add some basic tests for each plugin.

Overall this is very helpful as is, thanks!

Copy link
Collaborator

@edemaine edemaine left a comment

Choose a reason for hiding this comment

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

This is so exciting! Mainly some docs comments, plus I wonder:

Should @danielx/civet be a peerDependency (maybe with * or >= version) instead? Otherwise, wouldn't we need to publish this plugin after every Civet update? Hmm, or maybe package managers deal with this properly when versions don't mismatch. Indeed, I see vite-plugin-civet uses a dependency not a peerDependency, and I haven't had issues with using newer versions. But we still might want * or >= version dependency here so it will default to the latest or whatever dependency is in the project root (I hope?).

Update the Civet package build step so that people won't need to install a separate package and will be able to import any plugin directly.

I think this is how it works already. Even peerDependencies seem to install by default though (despite not for a while).

Reading https://nodejs.org/en/blog/npm/peer-dependencies, it seems like peerDependency is the "right" thing here, but I'm not certain how it works with a regular dependency...


- `dts`: `unplugin-civet` also supports generating `.d.ts` type definition files from the civet source, which is useful for building libraries.
- `outputExtension`: Output filename extension to use. Default: `.civet.jsx`, or `.civet.tsx` if `js` is `false`.
- `js`: Whether to transpile to JS or TS.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you state the default here? I believe it's false, in which case should also rewrite the .civet.jsx default for outputExtension. (Should be .civet.tsx, unless js is true.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah that should be corrected. Though now that I think of it, maybe js should be true by default. Most users would be using these for building applications and not libraries and in that case preserving types doesn't help much. I'm open to other opinions on this

Copy link
Collaborator

Choose a reason for hiding this comment

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

A default of js: true would break dts: true. We could make dts imply js: false, but honestly js: false is safer; some TypeScript features are not correctly implemented by Civet with js: true, and it just costs a bit of time to use already existing TS integration. So I think js: false is best.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We could give imply js based on the value of dts first,

const transpileToJS = options.dts || options.js;

in which case both options should work. My main concern was that rollup and webpack can't process typescript without additional plugins, so would need to set js: true to make the setup work, but if js: false has better typescript features then let's go with that default.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe we can include the {js: true} in the README where we give recommended workflows for Webpack and Rollup?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, we can do that

integration/unplugin/README.md Outdated Show resolved Hide resolved
@Mokshit06
Copy link
Contributor Author

Thank you!

Update the Civet package build step so that people won't need to install a separate package and will be able to import any plugin directly.

I assume you're talking about building this and outputting to dist like done for esbuild plugin in build/build.sh?

Should @danielx/civet be a peerDependency

I thought that peer dependencies were not installed by default, didn't realise that changed in v7. If we update the Civet package and include it in @danielx/civet then we won't require it, but if not, then keeping it a peer dependency is probably better.

@edemaine
Copy link
Collaborator

Oh, sorry, now I understand Daniel's comment: make this part of the @danielx/civet NPM package. I feel like separately released NPM packages is more common here, but I imagine the extra JS here is pretty minimal so it might make sense (and be convenient) to just include it. This would mean a bunch of the exports mappings in package.json should go to the top level.

@STRd6
Copy link
Contributor

STRd6 commented Aug 15, 2023

I assume you're talking about building this and outputting to dist like done for esbuild plugin in build/build.sh?

Yes, that's correct. Also updating the root Civet package.json to expose ./unplugin, ./vite, ./esbuild, etc. We could also replace the existing esbuild plugin that is already exported with this to cut down on duplication.

It will bulk up the published package a little bit compared to separate packages but should tree-shake out just fine thanks to the import mappings.

Let me know if you have any questions about the build step, it's currently manually building a few different files that end up in dist.

Thanks again!

- `dts`: `unplugin-civet` also supports generating `.d.ts` type definition files from the civet source, which is useful for building libraries. Default: `false`.
- `outputExtension`: Output filename extension to use. Default: `.civet.tsx`, or uses `.civet.jsx` if `js` is `true`.
- `js`: Whether to transpile to JS or TS. Default: `false`.
- `transformOutput`: Adds a custom transformer over jsx/tsx code produced by `civet.compile`.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Minor point: It might be worth keeping the text that described the arguments to the function.

@Mokshit06 Mokshit06 temporarily deployed to build August 15, 2023 17:21 — with GitHub Actions Inactive
@Mokshit06
Copy link
Contributor Author

Should be now exported from @danielx/civet!

@edemaine
Copy link
Collaborator

I think tsup devDependency is missing. I get

'tsup' is not recognized as an internal or external command,

@Mokshit06
Copy link
Contributor Author

You have to run yarn add inside integration/unplugin as well

@edemaine
Copy link
Collaborator

But build is failing; see CI. Does Yarn support submodules so that yarn would recursively yarn in there? (I'd also like to switch to pnpm where this would be easy...) Otherwise it would need to be in the build script, but that seems bad.

@Mokshit06
Copy link
Contributor Author

Yarn does support workspaces, but for that the root package.json should have private: true, which can't be the case for @danielx/civet as it needs to be published. I think we need to add it to the build script

@Mokshit06 Mokshit06 temporarily deployed to build August 15, 2023 19:24 — with GitHub Actions Inactive
@edemaine
Copy link
Collaborator

edemaine commented Aug 15, 2023

That's too bad. Would it be better if there was no package.json within integration/unplugin? Maybe the script and dep should just move to the top level. I don't like the idea of running yarn install every build...

@Mokshit06
Copy link
Contributor Author

Mokshit06 commented Aug 16, 2023

Hm so we could either move the dependencies up to the top level (shouldn't require moving the script), or we can do yarn add inside integration/unplugin on postinstall. That way whenever yarn add is ran on the top level, the unplugin deps should also be installed

@edemaine
Copy link
Collaborator

Either way seems workable to me, though I'm not sure for the motivation of a separate package.json if we're fully integrating. @STRd6 do you have a preference?

@Mokshit06
Copy link
Contributor Author

I think that's a fair point. Adding it to top level 👍

Copy link
Collaborator

@edemaine edemaine left a comment

Choose a reason for hiding this comment

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

Now there seems to be an infinite build loop, both for me and for CI:

yarn build                                                    (unplugin-civet $)
yarn run v1.22.18
$ bash ./build/build.sh
$ bash ./build/build.sh
$ bash ./build/build.sh
$ bash ./build/build.sh
$ bash ./build/build.sh

Maybe you're using a different version of Yarn? v1 is standard, not v2. Or maybe you didn't test. 😉

Because there's no longer a integration/unplugin/package.json, I believe yarn --cwd ./integration/unplugin build just runs the same script as yarn build. I think you want to run tsup instead. Also, can you add type checking to the top-level yarn test script?

@Mokshit06
Copy link
Contributor Author

Yeah I think I didn't test this change 😆 I have added a private package.json for integration/unplugin as calling tsup from root package.json required rewriting all paths in integration/unplugin/tsup.config.ts to be relative to the root rather than the unplugin directory.

@Mokshit06 Mokshit06 temporarily deployed to build August 19, 2023 21:24 — with GitHub Actions Inactive
@@ -1,4 +1,5 @@
import { TransformResult, createUnplugin } from 'unplugin';
// @ts-ignore
Copy link
Collaborator

Choose a reason for hiding this comment

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

This doesn't seem to be necessary. Right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hm yeah it looks like it works without this as well. That's weird because earlier it was throwing a type error that @danielx/civet is not available to integration/unplugin

@@ -54,7 +54,7 @@
"docs:build": "yarn build && vitepress build civet.dev",
"docs:preview": "yarn build && vitepress preview civet.dev",
"prepublishOnly": "yarn build && yarn test",
"test": "c8 mocha"
"test": "c8 mocha && tsc"
Copy link
Collaborator

Choose a reason for hiding this comment

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

@STRd6 This is going to interact with #638. But I guess we can always add to exclude until we're ready.

Copy link
Collaborator

Choose a reason for hiding this comment

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

#638 is now merged. Can you merge main and test what happens now? We might need to exclude it for now.

// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
// "skipLibCheck": true /* Skip type checking all .d.ts files. */
"skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this needed, given that you're excluding dist directories? It would be better to leave it false if possible. Ah, I see, it turns off checking of node_modules, which currently fails (from missing @types perhaps?). Still, seems like this turns off a lot of actual type checking... though we could leave it for later. Same for skipDefaultLibCheck which seems risky.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is needed because unplugin's dts imports webpack, vite, rollup, rspack, and esbuild out of which we don't have webpack and rspack required in Civet, and @typescript/vfs imports lz-string. So when typescript does type checking it errors out on these imports. We could also install types for these packages, or add them to dev deps instead

Copy link
Contributor

Choose a reason for hiding this comment

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

Adding dev dependencies for types sounds good.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Tried adding them to dev dependencies, but @rspack/core has a type error in it's declarations (imports a dts file that doesn't exist) and type checking fails because of it. Maybe we should turn on skipLibCheck for now? skipDefaultLibCheck won't be required

# unplugin
yarn --cwd ./integration/unplugin build
cp ./integration/unplugin/dist/* ./dist

Copy link
Collaborator

Choose a reason for hiding this comment

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

For Windows, I realize chmod a-x dist/*.*[jt]s would be helpful.

Also, what is this new dist/chunk-UZRN3RFA.mjs file? Presumably it's not desired?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For the esm build, tsup splits the common chunks into a separate file by default. As all the bundler entrypoints /esbuild, /rollup etc. import the central civetUnplugin it splits that into this chunk and imports it in them. Mostly helps keep the bundle size smaller as its not duplicated

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah, that is nice. Can we choose a better name for that file? Given that there's only one, maybe a custom name rule would work?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can choose a better name for it https://esbuild.github.io/api/#chunk-names, but i'm not sure if we should. There currently only exists one of these, but might be more than that in the future. I would suggest keeping it as is, or just turning off splitting

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it would be nice to rename it for now; we can always change it if we need multiple chunks in the future (seems unlikely for the unplugin?). Maybe unplugin-shared?

Copy link
Collaborator

@edemaine edemaine left a comment

Choose a reason for hiding this comment

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

I realize the examples from your repo aren't here. Probably they should be, for manual testing and for documentation?

Also, a reminder to finish the last couple tweaks here — would be great to get this out!

@Mokshit06
Copy link
Contributor Author

Should be good to land now!

@STRd6
Copy link
Contributor

STRd6 commented Aug 30, 2023

TS errors may be fixed by merging latest main now that our internals are in Civet.

@Mokshit06 Mokshit06 temporarily deployed to build August 31, 2023 15:30 — with GitHub Actions Inactive
Copy link
Contributor

@STRd6 STRd6 left a comment

Choose a reason for hiding this comment

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

👍 Looks good!

@edemaine any further comments?

@Mokshit06 Mokshit06 temporarily deployed to build August 31, 2023 18:14 — with GitHub Actions Inactive
Copy link
Collaborator

@edemaine edemaine left a comment

Choose a reason for hiding this comment

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

Looks good to me! Just tried out building including some examples.

types/node.d.ts Outdated
@@ -1,6 +1,6 @@
// Add _compile to Module
declare namespace NodeJS {
interface Module {
_compile(content: string, filename: string)
_compile(content: string, filename: string): any;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd prefer : unknown

@@ -0,0 +1,21 @@
# build output
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this directory should be called astro not astro-example.

@@ -182,51 +182,101 @@
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz#bafb75234a5d3d1b690e7c2956a599345e84a2fd"
integrity sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==

"@esbuild/[email protected]":
Copy link
Collaborator

Choose a reason for hiding this comment

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

yarn.lock might need updating; it changed when I ran yarn

@Mokshit06
Copy link
Contributor Author

Made the suggested changes!

@Mokshit06 Mokshit06 temporarily deployed to build August 31, 2023 19:52 — with GitHub Actions Inactive
@edemaine edemaine merged commit 5abce0f into DanielXMoore:main Aug 31, 2023
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants