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

Structure lifecycle hooks, add links to build time hooks #3418

Merged
merged 4 commits into from Mar 5, 2020

Conversation

lukastaegert
Copy link
Member

This PR contains:

  • bugfix
  • feature
  • refactor
  • documentation
  • other

Are tests included?

  • yes (bugfixes and features will not be merged without tests)
  • no

Breaking Changes?

  • yes (breaking changes will not be merged unless absolutely necessary)
  • no

List any relevant issue numbers:
Resolves #3409

Description

This will

  • split up the hooks in the documentation into build phase and output generation phase hooks
  • mention in the beginnings of these sections which are the first and last hooks of each phase
  • add to each hook which hooks precede and follow it

This is still WIP. The build phase is already done, I hope to finish the output generation phase until tomorrow. Feedback already welcome.

@codecov
Copy link

codecov bot commented Mar 3, 2020

Codecov Report

Merging #3418 into master will not change coverage by %.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #3418   +/-   ##
=======================================
  Coverage   93.29%   93.29%           
=======================================
  Files         172      172           
  Lines        6112     6112           
  Branches     1822     1822           
=======================================
  Hits         5702     5702           
  Misses        218      218           
  Partials      192      192           

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9d68d8e...56cf10a. Read the comment docs.

Copy link
Contributor

@jakearchibald jakearchibald 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 looking great. The split between 'build' and 'output generation' really improved my understanding here.

docs/05-plugin-development.md Outdated Show resolved Hide resolved
docs/05-plugin-development.md Outdated Show resolved Hide resolved
docs/05-plugin-development.md Show resolved Hide resolved
docs/05-plugin-development.md Outdated Show resolved Hide resolved
docs/05-plugin-development.md Outdated Show resolved Hide resolved
@lukastaegert lukastaegert marked this pull request as ready for review March 4, 2020 06:00
@lukastaegert
Copy link
Member Author

I finished adding the remaining links to the output generation hooks and addressing the current review comments. Please have a look if you see anything that could be improved. Also note that I am still no native speaker so if you think something could be spelled out in a more natural way, do not hesitate to comment 😜

@lukastaegert
Copy link
Member Author

This is looking great. The split between 'build' and 'output generation' really improved my understanding here.

Thanks. And yes, this is something that I stumbled upon myself while extending the documentation. E.g. resolveId and resolveDynamicImport are a build phase hook while resolveFileUrl and resolveImportMeta are output generation hooks, the naming does not really help here. As most plugins will probably be concerned mainly with one of the two phases, this split seemed helpful to me and you confirmed this. In retrospective, renderFileUrl and renderImportMeta would have probably been better names 🙄

Copy link
Contributor

@jakearchibald jakearchibald 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, although it still isn't clear to be when Rollup performs hashing, dead code removal, splitting etc.

docs/05-plugin-development.md Outdated Show resolved Hide resolved
@@ -225,20 +225,21 @@ You can use [`this.getModuleInfo`](guide/en/#thisgetmoduleinfomoduleid-string--m
#### `watchChange`
Type: `(id: string) => void`<br>
Kind: `sync, sequential`<br>
Previous/Next Hook: This hook can be triggered at any time both during the build and the output generation phases.
Previous/Next Hook: This hook can be triggered at any time both during the build and the output generation phases. If that is the case, the current build will still proceed but a new build will be scheduled to start once the current build has completed, starting again with [`options`](guide/en/#options).
Copy link
Contributor

Choose a reason for hiding this comment

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

This is great! I was never sure if build re-runs were sometimes shortcut. This makes it clear.

docs/05-plugin-development.md Outdated Show resolved Hide resolved
@jakearchibald
Copy link
Contributor

jakearchibald commented Mar 4, 2020

In case it's useful, here's how I interpreted the steps:

A CLI build will do the following:

  1. Build.
  2. If the previous steps did not error, for each set of output options, generate output.
  3. If in watch mode:
    1. If a watched file has changed, go to 1.
    2. Wait for a watched file to change.
    3. Go to 1.

If in watch mode, and any watched file changes, immediately hook: watchChange.

The rollup API will let you call build and generate output separately.


To build:

  1. Hook: options.
  2. Hook: buildStart.
  3. For each entry point, in parallel, go to step 2 of load module, and wait for all to complete.
  4. Perform treeshaking across modules.
  5. Perform code splitting. (this step is likely to move)
  6. Hook: buildEnd.

To load module:

  1. Hook: resolveDynamicImport for this module ID.
  2. If not resolved, hook: resolveId for this module ID.
  3. Hook: load using the resolved ID.
  4. Hook: transform using the loaded module.
  5. Perform these in parallel, and wait for all to complete:
    • For each import within the transformed module, in parallel, go to step 2, and wait for all to complete.
    • For each dynamic import within the transformed module, in parallel, go to step 1, and wait for all to complete.

To generate output:

  1. Hook: outputOptions.
  2. Try:
    1. Hook: renderStart.
    2. Perform these in parallel, and wait for all to complete:
      • Hook: banner
      • Hook: footer
      • Hook: intro
      • Hook: outro
    3. For each chunk that will contain a hash in its output filename, hook: augmentChunkHash.
    4. Generate hashes for files. (this step is likely to move)
    5. For each chunk, for each use of import.meta.:
      1. If the next text is ROLLUP_FILE_URL_, hook: resolveFileUrl.
      2. Else, hook: resolveImportMeta.
    6. For each chunk, hook: renderChunk.
  3. Catch:
    1. Hook: renderError.
    2. Return.
  4. Hook: generateBundle.
  5. If writing output, hook: writeBundle.

@lukastaegert
Copy link
Member Author

Nice, this looks quite good! Minor points:

  • While watch mode is correct in essence, the way you wrote it it does not belong to the build phase but rather to the generate phase. Watch mode KNOWS how many outputs there are. The logic is: Once the last output has been generated and a file has change, go to build 1 (otherwise wait etc.)
  • resolveFileUrl and resolveImportMeta are not two separate loops but rather the same loop that just looks for all usages of import.meta.something and then executes either of the two depending on something
  • generateBundle also has a possible return depending on how Rollup was called

@lukastaegert
Copy link
Member Author

lukastaegert commented Mar 4, 2020

Looks good, although it still isn't clear to be when Rollup performs hashing, dead code removal, splitting etc.

Well, that was not the question you asked 😉. So to answer it: hashing is performed just after the augmentChunkHash is called (basically it is called as part of the process). But I would not want to document this as this is definitely about to change once the hashing is redone.

Dead code elimination (or rather "tree-shaking" as we like to call it here 😄) is performed once all modules are loaded, so between the last transform and before buildEnd. This is something that we could document as I expect this to remain stable.

Code-splitting is also done in the build phase at the moment, after tree-shaking and before buildEnd. This is something I would not want to document as I very much want to move this to the output generation phase at some point. It is not too costly but having code-splitting per output would allow to make inlineDynamicImports an output option or have output-specific helpers injected as virtual modules into the build, e.g. helpers to unpack external namespaces from AMD or CJS.

Also there is some demand to open it up more to plugins e.g. to merge small chunks. It would be nicer if this was possible per output.

@jakearchibald
Copy link
Contributor

The logic is: Once the last output has been generated and a file has change, go to build 1 (otherwise wait etc.)

Isn't that what I wrote? See step 6 of build.

  • resolveFileUrl and resolveImportMeta are not two separate loops but rather the same loop that just looks for all usages of import.meta.something and then executes either of the two depending on something

Ohh nice! I've updated the post. What about renderChunk, is that a separate loop?

  • generateBundle also has a possible return depending on how Rollup was called

Isn't that covered in the next step: If writing…

Looks good, although it still isn't clear to be when Rollup performs hashing, dead code removal, splitting etc.

Well, that was not the question you asked 😉.

Hmmm kinda? In #3409 (comment) I call out that it's currently difficult to figure out the order in which hooks are called, and how it relates to the rest of Rollup's processing. I also called out #2739 - it isn't clear from the docs that renderChunk comes after hashing.

So to answer it: hashing is performed just after the augmentChunkHash is called (basically it is called as part of the process)

Is that also when asset hashing happens?

But I would not want to document this as this is definitely about to change once the hashing is redone.

Hmm ok. Is hashing likely to be redone in the next 6 months? Otherwise it might be worth noting it, to avoid more confusion like #2739.

I've added the other steps too, but noted that hashing and splitting are likely to move. Thanks for taking the time to work on this!

@lukastaegert
Copy link
Member Author

lukastaegert commented Mar 4, 2020

Isn't that what I wrote? See step 6 of build.

Yes, but it does not happen at the end of "build", it happens at the end of "generate output" for the last output

Ohh nice! I've updated the post. What about renderChunk, is that a separate loop?

Yes

Isn't that covered in the next step: If writing…

Ah, I overlooked this 👍

Hmmm kinda? In #3409 (comment) I call out that it's currently difficult to figure out the order in which hooks are called, and how it relates to the rest of Rollup's processing. I also called out #2739 - it isn't clear from the docs that renderChunk comes after hashing

Ok sorry, seems my mind had simplified this a little too much.

Is that also when asset hashing happens?

No, those are currently hashed when they are emitted or their source is set as you cannot change the source later.

Hmm ok. Is hashing likely to be redone in the next 6 months

I would think so. Documentation alone will not prevent new bugs from appearing here I fear.

I've added the other steps too, but noted that hashing and splitting are likely to move. Thanks for taking the time to work on this!

And thanks for pushing here! There are some comments from you that I will also add later before publishing this.

@jakearchibald
Copy link
Contributor

jakearchibald commented Mar 4, 2020

Isn't that what I wrote? See step 6 of build.

Yes, but it does not happen at the end of "build", it happens at the end of "generate output" for the last output

Ah, in step 7 of build I call out to generate output, so the watch stuff does happen after generate. I think the problem here is I've rolled generate output into build, whereas in the guide you've kept them seperate. I'll do the same to match. Done! I've added "A CLI build will do the following:" to tie them together.

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.

Document next steps for each hook
2 participants