Skip to content

new styles extractor#353

Merged
zamotany merged 3 commits into
callstack:developfrom
Anber:extractor
Apr 17, 2019
Merged

new styles extractor#353
zamotany merged 3 commits into
callstack:developfrom
Anber:extractor

Conversation

@Anber

@Anber Anber commented Mar 12, 2019

Copy link
Copy Markdown
Collaborator

Summary

This is a PoC of more advanced styles extractor. It can evaluate almost any js code whereas current extractor has problems with code like this:

const object = { fontSize: 12 };
object.fontWeight = 'bold';
export default styled.h1`
  ${object};
`;

Unlike current implementation, this extractor does not evaluate expressions immediately in TaggedTemplateExpression visitor but collects them for later evaluation. Then it builds a dependency graph for all expressions and strips all unrelated code from a module. On the last stage, it does a batch evaluation of all expressions.

I've created this PR in WIP stage because I had a bit painful merge after 1.3.1 release and I also found your typescript branch :)
So if you like it I will do some refactoring and rewrite to TS.

Test plan

New tests were added, old tests still work except one test with invalid code and two tests that check dependency extraction during evaluation.

@satya164

Copy link
Copy Markdown
Member

So awesome! I didn't have time to look at the code yet but will be looking when I have time.

Don't worry about my TypeScript branch for now. I don't think I'll have time to complete it this month. But if you want to use TypeScript, maybe you can use it for the new code you write. Then when we migrate, we will only need to migrate the old code.

@Anber

Anber commented Mar 12, 2019

Copy link
Copy Markdown
Collaborator Author

It would be better if you didn't look at the code now :)
I will have finished it and cover with comments by the end of the week.

@Anber

Anber commented Mar 14, 2019

Copy link
Copy Markdown
Collaborator Author

I guess it's ready for review.
There are still two failed tests. I will try to find the reason of failure but it would be great if you checked the tests itself.

@Anber Anber changed the title wip: new styles extractor new styles extractor Mar 15, 2019
@satya164 satya164 requested a review from zamotany March 15, 2019 09:21
@zamotany

Copy link
Copy Markdown
Contributor

Hey, @Anber thank you for your PR. We really appreciate your contribution and we would like to have it merged, but at the time being I'm having a hard time understanding the code without types, so here's what we are going to do: I'll finish up the migration to TS and then I'll ask you to migrate your code. Sorry for requesting more work from your side. I hope you'll understand our decision.

@Anber

Anber commented Mar 15, 2019

Copy link
Copy Markdown
Collaborator Author

Hi!

It’s ok. Can I take @satya164’s branch as a base for migration?

@zamotany

Copy link
Copy Markdown
Contributor

@Anber Yes, I'll be finishing up the migration on @satya164's branch.

@Anber Anber changed the base branch from master to @satya164/typescript March 15, 2019 19:41
@Anber

Anber commented Mar 15, 2019

Copy link
Copy Markdown
Collaborator Author

I've finished with shaker.ts, depsGraph.ts and scope.ts. The rest I'll migrate when you finish with the base branch.

@Anber

Anber commented Mar 26, 2019

Copy link
Copy Markdown
Collaborator Author

@zamotany I have some free time, can I help you with migration?

@zamotany

Copy link
Copy Markdown
Contributor

@Anber I'm in the process of setting up the infra for the migration (build pipeline, ESLint, etc), once it's done, you can jump in and help me migrate files. I was thinking about migrating the source code only first (excluding test, fixtures, website etc), since it can be done later.

@Anber

Anber commented Mar 27, 2019

Copy link
Copy Markdown
Collaborator Author

@zamotany Ok. Let's me know when you will be ready!

@zamotany

zamotany commented Apr 2, 2019

Copy link
Copy Markdown
Contributor

@Anber I have setup the infra for the migration here: https://github.com/callstack/linaria/tree/feature/typescript-migration so you can do PRs agains this branch feature/typescript-migration. The script typecheck and lint might fail, but the important one is test - the test must always pass. I'll be working on making typecheck and lint scripts to pass with both JS (w/ Flow) and TS present.

@Anber Anber changed the base branch from @satya164/typescript to feature/typescript-migration April 2, 2019 14:04
@Anber

Anber commented Apr 2, 2019

Copy link
Copy Markdown
Collaborator Author

I've changed the PR base. There are still two failed tests with dependencies that I mentioned before but everything else seems to be ok.
I'll finish with typings when typecheck is ready.

@Anber

Anber commented Apr 2, 2019

Copy link
Copy Markdown
Collaborator Author

@satya164 could you please check tests handles wrapping another styled component and handles escapes properly?

  • handles complex component expects core-js/modules/es6.string.raw as a dependency and it looks strange to me;
  • handles wrapping another styled component expects ../react but I think, we don't really need it for extraction, so it's not a real dependency.

@Anber

Anber commented Apr 3, 2019

Copy link
Copy Markdown
Collaborator Author

I've migrated src/babel to TS.

@Anber

Anber commented Apr 4, 2019

Copy link
Copy Markdown
Collaborator Author

➜ linaria ✗ yarn tsc --noEmit
✨ Done in 7.13s.

@zamotany

zamotany commented Apr 4, 2019

Copy link
Copy Markdown
Contributor

@Anber Awesome, incredible work, do you want to create a separate PR with the TS migration for src/babel or do you want to keep it in this one.
Maybe we should create a separate branch like develop from master for TS and avoid blocking master for critical bug fixes. WDYT? @Anber @satya164 @thymikee

@Anber

Anber commented Apr 4, 2019

Copy link
Copy Markdown
Collaborator Author

New branch for the next big release sounds good. We can collect all potential BC features in it and publish something like canary.

@thymikee

thymikee commented Apr 5, 2019

Copy link
Copy Markdown
Member

+1 for migrating under a dedicated branch

@zamotany

zamotany commented Apr 5, 2019

Copy link
Copy Markdown
Contributor

@Anber I have created a dedicated branch develop (https://github.com/callstack/linaria/tree/develop) from master, so can you open a PR agains that branch with just old files (excluding the new styles extractor) migrated to TS? If there are some JS files left, don't worry about those.

@Anber Anber changed the base branch from feature/typescript-migration to develop April 5, 2019 10:31
@Anber

Anber commented Apr 5, 2019

Copy link
Copy Markdown
Collaborator Author

I'll try to separate extractor and migration to two different PR but it wouldn't be simple, so I need some time.

@zamotany

zamotany commented Apr 8, 2019

Copy link
Copy Markdown
Contributor

@Anber just extract the files that are common to develop and extractor branch and make a PR with those. I'll migrate the missing ones. The reason I'm not taking your files that are common and integrating them into develop, instead I ask you to do so, it that I don't want to take away your contributions from the history.

Also, how about moving the files related to dep grath etc to a separate directory? Instead them living in utils it would be sth like dependencyExtractor??

@Anber

Anber commented Apr 8, 2019

Copy link
Copy Markdown
Collaborator Author

Hi @zamotany!
I'll do it in the next two or three days.

how about moving the files related to dep grath etc to a separate directory

It's a good idea!
depsGraph is closely linked to shaker and evaluate, so maybe we will move all of them to the separate directory evaluate or smth like this?

@zamotany

zamotany commented Apr 8, 2019

Copy link
Copy Markdown
Contributor

@Anber that's fine too. Also I think you can update those 2 failing snapshots.

@Anber Anber mentioned this pull request Apr 10, 2019
@zamotany

Copy link
Copy Markdown
Contributor

@Anber can you resolve the conflicts?

@callstack-bot

callstack-bot commented Apr 11, 2019

Copy link
Copy Markdown

Hey @Anber, thank you for your pull request 🤗.
The coverage report for this branch can be viewed here.

@Anber

Anber commented Apr 11, 2019

Copy link
Copy Markdown
Collaborator Author

@zamotany, I hope, now it's ready for review :)

@zamotany zamotany left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe we should call dumpNode if some environment variable is set? Like LINARIA_DEBUG?

Comment thread src/babel/evaluate/depsGraph.ts Outdated
return (
this.edges
// shallowEqual is not defined
.filter(([a]) => (t as any).shallowEqual(a, like))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you explain what this comment is about and why are we casting t to any??

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Oops, I've missed the second part of the comment in babel typings. Anyway, I'll add this shallowEqual to DefinitelyTyped and remove this any when the new version of @types/babel__core is published.

Comment thread src/babel/evaluate/depsGraph.ts Outdated
return this.bindingsDependents.get(id) || [];
}

findDependencies(like: object) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
findDependencies(like: object) {
findDependencies(like: Object) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@zamotany I think object is preferred

Comment thread src/babel/evaluate/depsGraph.ts Outdated
);
}

findDependents(like: object) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
findDependents(like: object) {
findDependents(like: Object) {

Comment thread src/babel/evaluate/depsGraph.ts Outdated
}
}

class GraphBuilder {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we split those 2 classes into separate files?

Comment thread src/babel/evaluate/depsGraph.ts Outdated
}
}

private readonly graph: Graph;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
private readonly graph: Graph;
private readonly scope: ScopeManager = new ScopeManager();

Comment thread src/babel/evaluate/shaker.ts Outdated

const { type } = node;
// VISITOR_KEYS is not defined in babel typings
const keys: [keyof T] = (t as any).VISITOR_KEYS[type] || [];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe let's keep VISITOR_KEYS in some file, types.ts maybe, since it's used in multiple files.

Comment thread src/babel/evaluate/shaker.ts Outdated
}
}

return Object.keys(changes).length ? Object.assign({}, node, changes) : node;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
return Object.keys(changes).length ? Object.assign({}, node, changes) : node;
return Object.keys(changes).length
? { ...node, ...changes }
: node;

Comment thread src/babel/evaluate/shaker.ts Outdated
* Adds to the end of module export of array of evaluated values or evaluation errors.
* Returns new AST and an array of external dependencies.
*/
function shake(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
function shake(
export default function shake(

Comment thread src/babel/evaluate/shaker.ts Outdated
];
}

export default shake;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
export default shake;

Comment thread src/babel/evaluate/shaker.ts Outdated
}

const shaken = shakeNode(rootPath, alive) as t.Program;
// dumpNode(program, alive);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
// dumpNode(program, alive);

@Anber

Anber commented Apr 12, 2019

Copy link
Copy Markdown
Collaborator Author

@zamotany, done. I've split depsGraph into 4 files.

@zamotany zamotany left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks awesome but there is a problem - the website is failing to build:
Screenshot 2019-04-16 at 16 23 22

@zamotany

zamotany commented Apr 16, 2019

Copy link
Copy Markdown
Contributor

it's failing on this forEach (Visitors.ts:250:16):

const declared = this.meta.get('declared') as t.Identifier[];
      declared.forEach(n =>
        this.graph.externalDeps.push({
          source,
          local: n,
          imported: null,
        })
      );

@Anber

Anber commented Apr 16, 2019

Copy link
Copy Markdown
Collaborator Author

It had expected some variable declaration, but received bare require(…).

@zamotany zamotany merged commit d57e859 into callstack:develop Apr 17, 2019
@zamotany

Copy link
Copy Markdown
Contributor

Huge thanks @Anber 👍
I'll finish the migration of other JS files and hopefully soon, we'll do a release.

@Anber

Anber commented Apr 17, 2019

Copy link
Copy Markdown
Collaborator Author

Thank you!
Let me know if I can help you.

@Anber

Anber commented May 28, 2019

Copy link
Copy Markdown
Collaborator Author

handles complex component expects core-js/modules/es6.string.raw as a dependency and it looks strange to me;

It was an error :) I'll fix it soon.

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.

5 participants