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

Parcel 2: Asset methods #2335

Merged
merged 2 commits into from
Dec 2, 2018
Merged

Parcel 2: Asset methods #2335

merged 2 commits into from
Dec 2, 2018

Conversation

devongovett
Copy link
Member

This is an experiment with creating a mutable Asset class with some helper methods for transformers to use rather than only returning plain objects. The methods include things like getConfig and getPackage helpers, along with addDependency, addConnectedFile, and createChildAsset` mutation/factory methods. None of these are required - plain objects also work fine, and are converted on the fly by the transformer runner. I think it simplifies transformers quite a bit, and also simplifies the transformer runner.

@devongovett devongovett requested a review from padmaia November 29, 2018 05:54
}

if (result.ast && context.generate) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Wow, this change really makes the TransformerRunner easier to follow. Good work!

}

toJSON(): AssetOptions {
// Exclude `code` and `ast` from cache
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it make sense to also set code to null when the asset is finalized in TransformerRunner? I noticed these fields are getting removed when the asset is stringified going into the cache, but that's not what is passed back on a cache miss run, so some "code" is being stored in memory in the graph.

Copy link
Member Author

Choose a reason for hiding this comment

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

Probably. That's true, although when run in the worker farm the assets are converted to JSON to pass over the IPC back to the main process.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah I guess it wouldn't be every cache miss, just the cache misses before the workers warm up. Still probably better to guarantee it's removed once finalized though.

let cacheEntry = await this.runPipeline(
nextInput,
pipeline.slice(1),
null,
getNextContext(context, result)
generate
);

assets = assets.concat(cacheEntry.assets);
connectedFiles = connectedFiles.concat(cacheEntry.connectedFiles);
Copy link
Contributor

Choose a reason for hiding this comment

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

I got a little confused here because I thought that cacheEntry was only passed in to the first call of runPipeline. I guess it has part of the shape of a CacheEntry, but it might help to not give it the same name as a function parameter. Maybe nextPipelineResult?

Copy link
Member Author

Choose a reason for hiding this comment

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

👍 originally it was a full cache entry and then I changed it

@@ -85,8 +85,7 @@ export type SourceLocation = {
end: {line: number, column: number}
};

export type Dependency = {
sourcePath: FilePath,
export type DependencyOptions = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Kinda not feeling this name. What about DependencyDescription?

@@ -98,6 +97,16 @@ export type Dependency = {
meta?: JSONObject
};

export type Dependency = {
Copy link
Contributor

Choose a reason for hiding this comment

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

Wondering if this should be DependencyRequest? Kinda makes sense since it is a combination of a dependency "description" (or whatever we decide to name it) and the site where the dependency was requested from.

Copy link
Member Author

@devongovett devongovett Nov 30, 2018

Choose a reason for hiding this comment

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

The idea was that DependencyOptions was the options used to construct a Dependency. Maybe we could just unify them into one type. I just didn't like all the flow warnings created by some fields being optional (like id).

Alternatively, we could have Dependency be what the user specifies, and ResolverRequest be the one with the id on it. But then we would have to rename the dependencies field on an asset?

@@ -136,28 +111,27 @@ class TransformerRunner {
}

// If the generated asset has the same type as the input...
if (result.type === context.type) {
// TODO: this is incorrect since multiple file types could map to the same pipeline. need to compare the pipelines.
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you give an example of when this might happen?

Copy link
Member Author

Choose a reason for hiding this comment

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

i.e. in the default config, we have *.{js,mjs,es6} mapping to a single transformer pipeline. If someone had an .mjs file as input, but the output was always js from the transformer, then we'd get into an infinite loop here. So we should be comparing the pipelines, not the extensions.

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess I was thinking those would all still by type "js". Is type ever different than the extension?

Copy link
Member Author

Choose a reason for hiding this comment

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

Well we initialize type to the file extension at the start of the pipeline:
https://github.com/parcel-bundler/parcel/pull/2335/files#diff-e00a1c679d921332a0033bb784c5d4b7R54 This means that the input type might be mjs but the output of the transformer would be js. Currently the code would recurse and run the JS transformer again with an input type of js rather than stopping. So, we need to compare the pipeline rather than the type.

);

assets = assets.concat(cacheEntry.assets);
connectedFiles = connectedFiles.concat(cacheEntry.connectedFiles);
}
} else {
// Jump to a different pipeline for the generated asset.
let nextInput = transformerResultToInput(input, result);
let nextInput = input.createChildAsset(result);
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like this is already being done outside the if/else

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch!

@devongovett
Copy link
Member Author

Going to merge so I can use this in other work.

@devongovett devongovett merged commit 8dfb79b into v2-work-so-far Dec 2, 2018
@devongovett devongovett deleted the asset-methods branch December 2, 2018 01:00
@devongovett devongovett added this to the Parcel 2 milestone Dec 3, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants