-
Notifications
You must be signed in to change notification settings - Fork 10
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
WIP: Transforms API Part 2 - Pre/post transforms #450
Conversation
… add condition to enable
Currently have an issue with building for prod with sass plugin. Rollup is giving this error for an import of a sass library within a scss file. We're doing
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow! Lot of good work going on here! 🤩
Haven't had time to dig into the code too much itself but did a cursory glance to provide some initial thoughts and feedback to keep the conversation going.
Regarding the build error, what's happening is that right now Rollup only "knows" about JS (similar to webpack) and has to be "taught" everything else via plugins. Just like I've done for HTML and CSS, per the custom Rollup plugins I created. So having it try and process a .ts
or .scss
out of the box will yield what you see here.
So there are a couple approaches that come to mind that I was thinking about for how we would need to solve this:
- Do all transforms entirely via the CLI, so the output (including paths in HTML / CSS / JS) come out as web standard compatible (e.g. HTML / CSS / JS), before being fed into Rollup.
- Reuse transform logic such that any pre processing plugins like a
.ts
are turned into Rollup plugins on the fly and re-used during the bundle lifecycle.
Doing everything via our CLI would be my preferred control flow, so the CLI only spits out web standards and thus transformation process happens once. Maybe in dev mode we support .ts
extensions from the browser on the fly (so a user would literally see a network request for my-component.ts, and in build mode, re-write the files and paths as part of serialization step?
Not sure what your thoughts are on there?
Just some additional thoughts / questions / considerations:
- Can we rename transforms/ -> plugins/transforms/? I think we might end up having other types of default plugins possibly, and also our transforms themselves be exported as plugins, to keep things consistent.
- Can we try restoring our existing polyfill and google analytics plugins, I think those should probably be easy to restore now.
- For SASS and TypeScript plugins, we need README.md files for each of those packages. Should we also add a plugins table to the main project README so discoverability is easier for users? I think it might also make sense to submit those as their own PR since there's a lot of moving parts here and through our test cases we should be able to cover all the desired behavior and functionality. (What I would do is make a copy of this branch locally, then grab the code later and copy / paste into a new PR after this one is merged).
- Our default transforms should be plugins just in the same way our external plugins are. I don't think we should deviate / side step the same API we share with users.
- We shouldn't need to create "mock" packages just for testing. The existing Polyfill and GA plugins have their own test cases that should still work after implementing the new transform behavior.
- We should remove the placholder
- For documentation, I think it's time we will need to start documenting our work for "new" development happening so it doesn't get further out of date / stale. Today I plan on getting all current docs up to date to reflect what is in the current state of the
release/0.10.0
branch
For me, I just need to make sure to follow up on
- New issue custom content type transforms (e.g.
.ts
,.scss
) - make an issue for dev vs. prod toggle for our existing plugins (since you wouldn't really want polyfills and GA loading in development)
- Make sure TODOs from here are part of Roadmap To 1.0 And Beyond #418
|
||
response = { | ||
...transformedResponse | ||
let resp = orderedTransforms.reduce(async (promise, plugin) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why does this need to be async
? You have to go through each plugin sequentially anyway so this just feels like a lot of extra code / complexity for no real additional value from what I can tell?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because we have to wait for each plugin to complete and we have no idea how long it could take to transpile and could contain its own async code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm... so the expectation then will be that every transform needs to follow an async
paradigm and return a Promise?
Should that then apply to all TransformInterface
methods or just the transform method? I think probably just for the transform method itself could make sense. If so, please make sure to document that for users so they know that is in an async
method out of the box.
@@ -0,0 +1,64 @@ | |||
/* | |||
* Use Case |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These test transform cases should be within the CLI repo, not their own packages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
polyfills plugin has tests within its package?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, packages manage their own tests. But these are not actual packages though, we would definitely not be publishing these to npm. From what I gather they are they are here to purely to exercise the general business logic around pre and post transforms and that from a generic stand point those things work. (which is great!)
If so, just create a test case in the CLI package, like we have with our previous iterations of plugins, which we can probably all delete now and instead replace with one for testing these transform plugins.
@@ -0,0 +1,59 @@ | |||
const fs = require('fs'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here re: location (move to cli/tests)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, thinking we should save non web standard content types (.ts
, .scss
) for a third PR, and just focus on getting the pre / post sequencing established and supporting standard for this PR, which our Rollup configuration should already be able to handle out of the box.
That should still allow us to restore our existing plugins (Polyfills and Google Analytics) as part of this PR, so that would definitely be super valuable to accomplish and a good milestone for this work. We can dedicate time to discussing how to tackle the other content types in our next meeting.
the |
We have problems with the polyfills plugin in prod. We have to make an import map for all other dependent libraries it may load. It's a separate issue though that we're aware of relating to any imported libraries in general. Once you've had a look at it, I think we should disable it for this PR in greenwood.config.js and then revisit later. |
I think we just need to scan the HTML file for Then we just "catch" the file on the way out and if we need to rename or inline into the HTML or whatever, we can do that as well. Effectively, it's just this issue manifesting itself in another (similar) context. I think making a PR to fix #434 would instrument the mechanism you need for here. |
Ok had a little more time to think about this and left a comment re: handling JavaScript / CSS in inline I think I should be able to make the Polyfills plugin work with a little tweak to our current setup via amending the scope of #434 to support node_modules based paths via Will take a look a look into all this today. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might be missing something here, but I'm having some issues seeing the Google Analytics plugin working when running yarn build
. I think you had mentioned it should be working (but not Polyfills), but while i can log and see that the applyTransform
method is indeed getting called, I don't see the actual Google Analytics code in the final index.html files in the /public directory?
I think one way to validate the behavior would be to re-enable the test cases we already had for plugins to validate if the API is working the way we expect (and thus allows us to bump our test coverage back up!). I think if you can get the tests for both GA and Polyfills turned back on (and passing, at least for GA) and then the issues you are seeing become more easily reproducible for someone else, then I can definitely jump in and help out here a bit more. Also updated my comment with latest TODOs status. This means we should be able to delete those test packages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pushing up your latest changes. I've had some time to review a bit more in depth and I've been able to address the main issue of resolving the web components loader file, something along these lines
async applyTransform(response) {
return new Promise(async (resolve, reject) => {
try {
const isProdBuild = process.env.__GWD_COMMAND__ === 'build'; // eslint-disable-line no-underscore-dangle
const src = isProdBuild
? filename
: `${nodeModuleRoot}/${filename}`;
const body = response.body.replace(/<head>/, `<head>
<!-- Web Components poyfill -->
<script src="/${src}"></script>
`);
if (isProdBuild) {
fs.copyFileSync(
path.join(process.cwd(), nodeModuleRoot, filename),
path.join(this.context.outputDir, filename)
);
}
resolve({
body,
contentType: this.contentType,
extension: this.extensions
});
} catch (e) {
reject(e);
}
});
}
I would even go so far as to say that things like GA and Polyfills wouldn't even happen in development, but that would be up to the plugin author to support that. Or for testing, we / they can provide an explicit option to override. That is something I can make an issue for.
This does cause an error for Rollup though, since it's going to try and trace a direct path to webcomponents-loader.js via the <script>
tag in index.html to bundle it. (in this case, it still works for us though, at least)
[Error: ENOENT: no such file or directory, open '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/webcomponents-loader.js'] {
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: '/Users/owenbuckley/Workspace/project-evergreen/repos/greenwood/www/webcomponents-loader.js'
}
But this file in particular is explicitly not supposed to be bundled by its own design.
This was actually something we didn't have to contend with before but I did have a TODO as part of the refactor to come up with some sort of "teardown" or post-build action. 🙃
This is one case though, but it seems like maybe i just need to play around with this design a little bit more, so let me do that.
it doesn't look like fonts are correctly loading in development?
} | ||
|
||
shouldTransform() { | ||
const { request, workspace } = this; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should these two plugins only need to check for .html or does it have to also do it for .md too? Could these perhaps reuse the business logic of the our default transforms maybe?
Also, we should avoid doing this kind of logic, re: the replace('.html')
`${workspace}/pages${url.replace('.html', '')}`;
constructor(request, extensions, contentType = '') { | ||
const { context, config } = request.compilation; | ||
constructor(request, compilation, { extensions = [], contentType = '' }) { | ||
const { context, config } = compilation; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we just passthrough context / compilation? Otherwise it feels like we're just going to end repeating every property and have to keep updating / adding as context
and config
get updated, which seems like it would get annoying over time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for all your help on driving the design of this feature @hutchgrant . Although we'll be going with #466 , the spirit of Tranforms lives on, just with a different name. 😃
Good design often takes a couple tries to get right, but I think we can add Transforms / Resource to the list of pretty good design decision we've made for this project. And for the other ones, well, we're also doing a pretty good improving those, even coming up with our own solutions when needed. 🌟
Related Issue
#422
Summary of Changes
request
andcompilation
objectsgreenwood.config.js
with the same format as previous plugins we allowed through webpack etcshouldTransform()
is true.Example Plugins
HTML pre/post transforms plugins
to test rundisabled by default. see package for tests.yarn develop
and then visit transform-example.htmlAnother PR, another day
Sass preprocessor transform plugintest by runningyarn develop
and visiting any page.modified the app template to utilize a header component with .scss instead of css to demonstrate that the preprocessor transform functions as expected.simply import .scss file into any component withunsafeCSS(mysassfile.scss)
Typescript pluginto test, import a .ts file, in current branch one is already imported to the test-sass/header component. It outputs hello world to client console