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

Change build system and update Jest #747

Merged
merged 41 commits into from
Jul 2, 2018
Merged

Change build system and update Jest #747

merged 41 commits into from
Jul 2, 2018

Conversation

emmatown
Copy link
Member

@emmatown emmatown commented Jun 30, 2018

What:
This changes the build system from some npm scripts to some node scripts that run rollup on every package. This is extracted from https://github.com/emotion-js/next

This also moves the site out of the packages folder into the root directory because I wanted to make the packages folder only contain packages that are published to npm. The benchmarks package was also moved to the new scripts folder for the same reason.

Why:

  • Faster builds since a new process doesn't need to be started for each build
  • Everything runs through the same build system

How:

Checklist:

  • Documentation N/A
  • Tests
  • Code complete

@codecov
Copy link

codecov bot commented Jun 30, 2018

Codecov Report

Merging #747 into master will decrease coverage by 0.07%.
The diff coverage is 100%.

Impacted Files Coverage Δ
packages/babel-plugin-emotion/src/macro-styled.js 100% <ø> (ø) ⬆️
packages/create-emotion-server/src/index.js 100% <ø> (ø) ⬆️
packages/babel-plugin-emotion/src/macro.js 100% <ø> (ø) ⬆️
.../build/add-basic-constructor-to-react-component.js 100% <100%> (ø)
packages/babel-plugin-emotion/src/index.js 96.88% <100%> (+0.01%) ⬆️

@@ -0,0 +1 @@
module.exports = require('babel-plugin-emotion').macros.styled
Copy link
Member

Choose a reason for hiding this comment

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

whats the reason behind those 2 "proxy" files?

Copy link
Member Author

Choose a reason for hiding this comment

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

In case people have custom instances of emotion and they're using the macros with them since this they were previously imported via babel-plugin-emotion/lib/macro and babel-plugin-emotion/lib/macro-styled

Copy link
Member

Choose a reason for hiding this comment

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

gotcha, maybe add a comment that this can be removed with next major?

"prop-types": "^15.6.1",
"rimraf": "^2.6.1",
"rollup": "^0.60.1"
"prop-types": "^15.6.1"
Copy link
Member

Choose a reason for hiding this comment

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

seems weird to have prop-types in devDeps, are they needed here?

Copy link
Member Author

Choose a reason for hiding this comment

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

It was already there. It's probably not strictly necessary but it was probably added there because it's a peerDependency and it's needed in dev. If you think it should be removed them I'll remove it but IMO, it doesn't really matter.

Copy link
Member

Choose a reason for hiding this comment

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

peer dep thing makes sense 👍

name: 'ast-transform', // not required
visitor: {
Class(path) {
if (
Copy link
Member

Choose a reason for hiding this comment

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

could be made more readable with buildMatchMemberExpression & I would extract hasConstructor too

const isReactComponent = t.buildMatchMemberExpression('React.Component')

// ...

if (isReactComponent(path.node.superClass) && hasConstructor(path.node.body.body)) {
  // ...
}

)
})
) {
path.node.body.body.unshift(
Copy link
Member

Choose a reason for hiding this comment

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

lately i've become fan of template, IMHO it increases readability a lot - although not sure now if it will be possible to create a class method with it - we could always create dummy class with constructor only and just unpack constructor node though

@@ -0,0 +1,40 @@
// this is to avoid the spread argument helper for react component constructors
Copy link
Member

Choose a reason for hiding this comment

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

could u explain what exactly is avoided with this and why this is a problem?

Copy link
Member Author

Choose a reason for hiding this comment

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

https://runkit.com/mitchellhamilton/5b370eeaf5b34c0012874d92
Without this, the constructor's arguments will be iterated over and put in an array unnecessarily.

Copy link
Member

Choose a reason for hiding this comment

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

nice! this would be useful as part of preset-react, gonna propose it later to rest of the babel team

Copy link
Member Author

@emmatown emmatown Jun 30, 2018

Choose a reason for hiding this comment

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

BTW, this implementation isn't perfect since it should technically pass the second argument to super as well (and maybe the third but I don't know if that's strictly necessary). The reason I didn't do that here is that I know I won't access context in those cases.

https://github.com/facebook/react/blob/64e1921aab4f7ad7e2f345f392033ffe724e52e9/packages/react/src/ReactBaseClasses.js#L21-L29

Copy link
Member

Choose a reason for hiding this comment

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

no idea how updater arg might be used 🤔 we could do super(props, context, updater) by default + an option to optimize it to just super(props)

Not sure if context here is only for legacy purposes, or is the new one also passed here - anyway doesn't matter as long as this arg is here

@Andarist
Copy link
Member

Quite a lengthy PR 😉 have to go to sleep now, but gonna finish reviewing in few hours

}

function isPrimitive(val) {
return val == null || /^[sbn]/.test(typeof val)
Copy link
Member

Choose a reason for hiding this comment

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

i understand this regexp, but it looks slightly confusing at first - i'm unsure if u i.e. meant to catch symbol with it or not? would prefer inlining all possibilities here for clarity, especially that this is not a bytes-sensitive code

"del": "^3.0.0",
"rollup": "^0.62.0",
"rollup-plugin-alias": "^1.4.0",
"rollup-plugin-babel": "^4.0.0-beta.5",
Copy link
Member

Choose a reason for hiding this comment

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

it's safer to pin beta packages to exact versions, also - this could get upgraded, there is beta.7 already

@@ -0,0 +1,16 @@
{
"name": "build",
"version": "0.5.7",
Copy link
Member

Choose a reason for hiding this comment

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

does it make sense to version this?

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 think some tools(I think it's lerna and yarn but I'm not totally sure) complain when there isn't a version so since it doesn't really hurt anything, we might as well leave it.


if (!path.node.specifiers.length) {
path.remove()
}
Copy link
Member

Choose a reason for hiding this comment

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

as this is used as filter predicate would be good to return explicit boolean here

Copy link
Member Author

@emmatown emmatown Jun 30, 2018

Choose a reason for hiding this comment

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

This part isn't in the filter predicate.

Copy link
Member

Choose a reason for hiding this comment

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

oh, right, my bad 👍

['@babel/proposal-class-properties', { loose: true }],
require('./fix-dce-for-classes-with-statics'),
isBrowser && require('./inline-isBrowser'),
isBrowser &&
Copy link
Member

Choose a reason for hiding this comment

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

isnt this duplicating what inline-isBrowser.js do (except filtering imported specifiers)? why there are 2 similar plugins?

Copy link
Member Author

Choose a reason for hiding this comment

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

inline-isBrowser.js is replacing the usages of @emotion/utils in packages whereas this plugin is changing the declarations inside of @emotion/utils

Copy link
Member

Choose a reason for hiding this comment

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

could we maybe add a filename guard to this second plugin so it wont run accidentally on other packages? I think there are some nice new options in babel@7 - like overrides etc, maybe they could be leveraged to add this plugin only for certain filepaths/directories, this would make the intent more explicit

}
}
}),
'@babel/plugin-proposal-object-rest-spread'
Copy link
Member

Choose a reason for hiding this comment

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

might be a good moment to update babel@7 deps too and use loose for this plugin

@@ -0,0 +1,98 @@
const path = require('path')
const del = require('del')
Copy link
Member

Choose a reason for hiding this comment

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

seems like both rimraf and del are used across the codebase - not a big deal, but could be unified

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 think the usages of rimraf were only in npm scripts and I removed those ones so I don't think rimraf is being used anymore.

@@ -0,0 +1,45 @@
// @flow
Copy link
Member

Choose a reason for hiding this comment

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

is this file used? cant find the usage in this PR, I also don't quite get why this is needed - especially when you have removed those devDeps etc in this PR

or is it a helper script which u have used to modify packages in this PR + it can be used to modify them in the future? if so it would be great to add a comment about this

Copy link
Member Author

Choose a reason for hiding this comment

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

It's a helper script that can be used to modify the packages in the future, I'll add a comment.

@Andarist
Copy link
Member

The whole idea & setup looks way better than previous one 👍

I feel though that monorepo setup should be something "on top" of regular git repository - it's job is to ease dependency management & local development. IMHO even if it's kinda artificial problem most of the time I always strive for separating packages, their tooling etc - what I mean by that is that having a monorepo script i.e. to build stuff is a good thing for development but even having such it would be good to embed build tooling + devDeps etc in each package so it can be easily extracted from the monorepo and moved away. Proposed build setup could be packaged and handle both monorepo and single package use cases. I understand it's not really important right now so I propose to screw that for now, but create an issue about this once this PR gets merged.

}
if (ret.pkg['umd:main']) {
ret.configs.push({
config: makeRollupConfig(ret, true, true),
Copy link
Member

@Andarist Andarist Jun 30, 2018

Choose a reason for hiding this comment

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

would prefer changing signature to:

makeRollupConfig(data, { isBrowser = false, isUmd = false } = {}) {
  // ...
}

right now looking at this call site it's hard to tell what those booleans do

Copy link
Member

Choose a reason for hiding this comment

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

not yet sure about this but - I can't find a package using "browser" field, so not sure how exactly we need to handle it, but a good alternative to transforming packages with babel and replacing stuff with browser values it might be clearer to introduce BROWSER env variable, produce code conditionally with process.env ternaries in the actual code and prepare 2 builds with appropriate rollup-plugin-replace setup

Copy link
Member Author

Choose a reason for hiding this comment

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

The reason I didn't do that is I want to ship flow types from the source in v10 and using a global would require adding a declare var to every usage of it so that people don't get flow errors from it.

@Andarist
Copy link
Member

Andarist commented Jul 1, 2018

Continuing #747 (comment)

Should be possible to prepare multiple "source" directories - with only process.env replaced in them and build final bundles from them + ofc redirecting types to appropriate directories. It would be quite unconventional setup and slightly more complicated, but IMHO would be clearer in the actual source what are the possible code shapes, right now the babel plugin idea is hidden and can be broken more easily.

@emmatown
Copy link
Member Author

emmatown commented Jul 1, 2018

I was thinking of using plain globals but using process.env would probably just work since flow knows about process.env.

The other problem though is that the second variable shouldSerializeToReactTree, also depends on process.env.NODE_ENV when it's not in the browser build so either the check for that would have to be inlined or imported from @emotion/utils which is just an extra thing to deal with.

TBH, I think that even though it's not perfect, I'd rather just leave it right now since it's not getting used on the current packages here yet and it works.

@TrySound
Copy link
Contributor

TrySound commented Jul 1, 2018

Would be good to change es suffix to esm which is more descriptive like esm loader. The latest version of rollup also has esm alias for format which will replace es in the future. material-ui uses es to ship es6 (not only modules) syntax.

@emmatown emmatown merged commit aa8c4e4 into master Jul 2, 2018
@emmatown emmatown deleted the change-build branch July 2, 2018 01:31
@emmatown
Copy link
Member Author

emmatown commented Jul 2, 2018

Thanks for your review @Andarist!!

@Andarist
Copy link
Member

Andarist commented Jul 2, 2018

Not a problem, it was a cool PR to review! 😃

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