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

Babel v7 compatibility #3

Merged
merged 14 commits into from
Mar 19, 2018
Merged

Babel v7 compatibility #3

merged 14 commits into from
Mar 19, 2018

Conversation

jaydenseric
Copy link
Contributor

@jaydenseric jaydenseric commented Mar 19, 2018

With this update, the package should be compatible with both Babel v6 and v7.

  • Updated dependencies.
  • Removed the unused simple-assign dependency.
  • Plugin options now an object instead of a string (Babel v7 requirement).
  • Option is called moduleSpecifier:
    • This is how it is called in the modules spec.
    • Options default to use object-assign:
      • It's the most popular implementation.
      • IMO the strongest use case for babel-plugin-transform-replace-object-assign is to optimize React projects by configuring all plugins to output the Object.assign builtin (instead of helpers), then instead of polyfilling, replace all occurrences with the same object-assign dependency used by React.
  • declar to declare variable name typo fix.
  • Uses @babel/helper-module-imports to fix Support for CommonJS? #1. The output is either ESM or CJS depending if sourceType is module or script.
  • Updated tests and fixtures. Babel v7 outputs slight differences.
  • Disabled and ignored package-lock.json. Package lock files are for apps, not packages; npm blacklists them from ever being published.
  • Updated readme for the new API.
  • Replaced lodash.assign in readme examples with object-assign. It looks more intuitive and demos the defaults.

- Updated dependencies.
- Plugin options now an object instead of a string (Babel v7 requirement).
- Options default to use `object-assign`.
- Replaced `lodash.assign` in examples with `object-assign`.
- Updated tests and fixtures.
- Updated readme.
Package lock files are for apps, not packages; npm blacklists them from ever being published.
@jaydenseric
Copy link
Contributor Author

Please don't merge until I have a chance to integrate @babel/helper-module-imports, to fix #1.

@newoga
Copy link
Owner

newoga commented Mar 19, 2018

@jaydenseric This looks great. And looks like you wrapped up integrating @babel/helper-module-imports as well. Let me know if you're wrapped up.

IMO the strongest use case for babel-plugin-transform-replace-object-assign is to optimize React projects by configuring all plugins to output the Object.assign builtin (instead of helpers), then instead of polyfilling, replace all occurrences with the same object-assign dependency used by React.

That's interesting. If you're willing, I think this use case would great to add to the README.md as well.

Thanks for your contribution! 👍

@newoga
Copy link
Owner

newoga commented Mar 19, 2018

FYI I'm wondering what the best plan should be for releasing. Since this is a breaking change, we should consider a major bump (even though the previous version technically never was released at v1).

Since babel v7 is still in beta, I'm wondering whether or not we should publish this in npm has prerelease. That being said, it seems like babel 7 is pretty close to being wrapped up and I would be surprised if there were breaking changes in the plugin API at this point, so may be fine releasing a new stable. Let me know what you think.

@jaydenseric
Copy link
Contributor Author

I think this PR is ready, but won't be sure until I can test it locally on my real project using npm link, as per the React optimization use case. For some reason my AVA tests are erroring with ReferenceError: regeneratorRuntime is not defined, I want to be sure it's not related to this PR.

As for documenting the React optimization use case, I would like to streamline a recipe for it for a while first because the .babelrc.js config for it is not intuitive, here is a WIP:

const { engines: { node } } = require('./package.json')

module.exports = {
  comments: false,
  presets: [
    { plugins: ['babel-plugin-transform-replace-object-assign'] },
    [
      '@babel/env',
      {
        targets: { node: node.substring(2) }, // Strip `>=`
        modules: process.env.MODULE ? false : 'commonjs',
        loose: true
      }
    ],
    ['@babel/preset-react', { useBuiltIns: true }]
  ],
  plugins: [
    [
      '@babel/plugin-proposal-object-rest-spread',
      { loose: true, useBuiltIns: true }
    ],
    ['@babel/proposal-class-properties', { loose: true }]
  ]
}

For the release plan, maybe v1.0.0-alpha.1?

@newoga
Copy link
Owner

newoga commented Mar 19, 2018

I think this PR is ready, but won't be sure until I can test it locally on my real project using npm link, as per the React optimization use case. For some reason my AVA tests are erroring with ReferenceError: regeneratorRuntime is not defined, I want to be sure it's not related to this PR.

Okay, sounds good. Let me know what you find. I haven't moved to babel 7 in my projects yet so I don't have anything real to test this on.

That being said, I did pull this and ran the tests, which all looked good. But I do have some questions regarding the new fixtures. I will leave comments on the changes.

For the release plan, maybe v1.0.0-alpha.1?

Makes sense to me, once we iron out the kinks I'm fine going straight to beta unless we think API could change.

Copy link
Owner

@newoga newoga left a comment

Choose a reason for hiding this comment

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

I think the big question I have is with the test fixtures and making sure the expected.js files reflect what we're trying to test. It seems like the expected result is properly importing the configured Object.assign replacement but is not using it. Let me know what you think.


function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

(0, _simpleAssign2.default)({ a: 1 }, { b: 2 });
(0, _simpleAssign2.default)({ c: 3 }, { d: 4 });
_objectAssign({
Copy link
Owner

Choose a reason for hiding this comment

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

@jaydenseric Should this be _simpleAssign if this is working correctly?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm super confused. How come the tests used to pass with _simpleAssign expected, when the UID was hardcoded to objectAssign all along?

Copy link
Owner

Choose a reason for hiding this comment

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

Yeah, me too. It's be a while since I have looked at this (and babel plugin development in general). But it's possibly that in babel v6, babel always generated the UID for an import based on the package here. The generateUidIdentifier('objectAssign') may have been unnecessary/unused. Can't confirm that at the moment.

@jaydenseric
Copy link
Contributor Author

Finding issues when testing it on my project (although I worked out the regenerator runtime issue was something unrelated).

I was seeing import _objectObject from 'object-assign' instead of _objectAssign.

I don't know why the tests here don't exhibit the issue, but nameHint should be a simple string, which is what I thought generateUidIdentifier did. But it apparently makes an Identifier object, so I think we need to read just the name:

addDefault(
  file.path,
  moduleSpecifier,
  {nameHint: file.get(OBJECT_ASSIGN).name} // <-- This 
)

Since doing that though, now I always get import _objectAssign2 from 'object-assign'.

Note that all along, the instances in code are correctly _objectAssign. Only the default import names are wrong.

@newoga
Copy link
Owner

newoga commented Mar 19, 2018

That's interesting. Yeah, the tests also confuse me. The tests seem to indicate the plugin isn't working.

Since doing that though, now I always get import _objectAssign2 from 'object-assign'.

In your project, out of curiosity, are all the Object.assign calls referencing _objectAssign2?

@jaydenseric
Copy link
Contributor Author

In your project, out of curiosity, are all the Object.assign calls referencing _objectAssign2?

No, with {nameHint: file.get(OBJECT_ASSIGN).name} the calls are _objectAssign() while the import is _objectAssign2.

@newoga
Copy link
Owner

newoga commented Mar 19, 2018

Note that all along, the instances in code are correctly _objectAssign. Only the default import names are wrong.

And sorry if I'm misunderstanding, but you're saying that it is correct behavior for the calls to use _objectAssign? To me I figured it should be referencing the imported _objectAssign2 (which should be your object-assign import). What does _objectAssign reference exactly?

@newoga
Copy link
Owner

newoga commented Mar 19, 2018

@jaydenseric I'm sorry I can't be more helpful regarding the babel v7 API. While the subject matter interests me, I haven't explored it deeply so need to re-familiarize myself. The documentation I'm reading here for babel-helper-module-imports seems to imply that the nameHint options only works for named imports, not default imports via the addDefault method.

Is there any other documentation that says otherwise?

That being said, I'm still puzzled why path.scope.generateUidIdentifier('objectAssign') seemed to work with the different import name in previous versions.

It's past 1am in my timezone. I can investigate this more in the morning. Let me know what you find!

Thanks again @jaydenseric. 😄

@jaydenseric
Copy link
Contributor Author

Using prettier. Sorry, I could not live without it.
- Only destructure out the config when it is needed.
- No need to set an import name hint.
@jaydenseric
Copy link
Contributor Author

@newoga I think it's ready! Tested it out in the project, and it seems to work ok. Please take a look over the assertions, as I have updated them again; they now look more similar to what you originally had.

@jaydenseric
Copy link
Contributor Author

@newoga
Copy link
Owner

newoga commented Mar 19, 2018

Just pulled the latest, looks great! 👍And surprised to see the apollo graphql-client to go from 11 KB to 4 KB. I use Apollo's graphql libraries as well. 🎉

I have a few nit-picky things I'd like to add. If you have the time to tackle these I'd really appreciate it, otherwise, I can do them later this evening.

  1. Can we add a minimum version of npm v5 to the package.json engines since we are committing a package.lock file? Also debating just switching this to yarn/yarn.lock but I don't feel super strongly about it.
  2. Can we add @babel/core to the list of peerDependencies since the babel community decided to do that for all their internal plugins?
  3. Can we remove the prettier related development dependencies for now? While I love prettier and think it makes sense to implement, I'm thinking we should add it in a new PR along with some commit hooks using husky/lint-staged and possibly some basic linting. Feel free to do one pass through of prettier on the files (though if you could leave semi-colons on for now, it will make the diff easier to read for actual changes related to the babel 7 implementation).

I think we can do a release today as well. I'm half-tempted to release a new version of this plugin that supports babel v6 with the moduleSpecifier API changes. And then release your babel 7 supported version as v2. I think there are a number of projects waiting for a stable release of babel 7 before upgrading and if any of them depend on this, it will allow them to migrate to the new API before babel 7 is released.

@newoga
Copy link
Owner

newoga commented Mar 19, 2018

Also, forgot to mention, that new implementation of the plugin is super simple and clean. 👍 👍

newoga added a commit that referenced this pull request Mar 19, 2018
This commit is based on the new API proposed by @jaydenseric in his PR #3. His PR primarily adds support for babel 7. The PR also introduces some necessary breaking changes to the plugin configuration. This commit takes his new API and backports it to the babel 6 supported version of this plugin to ease migrations. The API changes are:

1. Configuration is now optional. If no config is provided, `object-assign` is used.
2. String based configuration is no longer supported. It must be an object with a `moduleSpecifier` key.

Documentation was updated and a new test fixture was addded to test the new default configuration behavior.
But first pretty everything, with semicons.
@newoga
Copy link
Owner

newoga commented Mar 19, 2018

@jaydenseric I'm going to cut a v1 release now. Sorry for creating all the extra work for you but after that's done, can you rebase this on top and then we can create a beta release with this (we can do a full release when babel 7 is stable).

@newoga
Copy link
Owner

newoga commented Mar 19, 2018

@jaydenseric I'm all wrapped up. Let's rebase this (might be a bit messy, sorry! 🙏) and merge!

Edit: Essentially for the merge, you can keep your version of all the changes, the only really nasty file might be the package.json which has some changed scripts and maybe the /test/index.js file which has some logic for the new test that was added.

# Conflicts:
#	README.md
#	src/index.js
#	test/index.js

Also, fixed tests and prettied code.
# Conflicts:
#	lib/index.js
@newoga
Copy link
Owner

newoga commented Mar 19, 2018

@jaydenseric All wrapped up? I pulled the latest and everything looks good to me. We just need to add a note in the ## Unreleased changes section about babel v7 compatibility and may adding ^7.0.0-beta.42 as a peerDependency (feel free to do that or I can before I bump the version). And then we can release.

I'm ready to merge when you are though 👍

@jaydenseric
Copy link
Contributor Author

It's ready!

@newoga newoga merged commit 17204f3 into newoga:master Mar 19, 2018
@jaydenseric jaydenseric deleted the babel-v7 branch March 19, 2018 23:50
@newoga
Copy link
Owner

newoga commented Mar 20, 2018

Thanks again @jaydenseric. This landed as 2.0.0-beta.0 or you can install via babel-plugin-transform-replace-object-assign@beta.

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.

Support for CommonJS?
2 participants