forked from Automattic/wp-calypso
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce Babel transform to convert 'lodash-es' imports to 'lodash' (A…
…utomattic#22187) * Introduce Babel transform to convert 'lodash-es' imports to 'lodash' Some 3rd party libraries like Redux Form or React Redux internally import Lodash functions from `lodash-es`. Because Calypso code imports from `lodash`, this leads to code duplication. This patch introduces a Babel transform to transform these imports to `lodash` and activates the transform on the `redux-form` and `react-redux` libraries. Because these libraries provide ES6 versions of their exports, we can use smart transform like this one. * Rewrite tests to not use snapshots * Add the lodash-es transform to server build and fix builds in test env Remove the babel-lodash-es transform from babelrc when building in NODE_ENV=test environment. In that case, the transform is already done in the Webpack loader. Having the transform in babelrc is useful only for Jest tests. Also, adds the transform to the server build and removes lodash vs. lodash-es duplication from the server bundle.
- Loading branch information
Showing
7 changed files
with
137 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
Lodash Babel Transform | ||
====================== | ||
|
||
This Babel transform transforms imports from the `lodash-es` module, commonly found in | ||
third party NPM packages, into imports from `lodash`: | ||
|
||
```js | ||
import get from 'lodash-es/get' | ||
``` | ||
|
||
is transformed into: | ||
|
||
```js | ||
import { get } from 'lodash' | ||
``` | ||
|
||
This transform avoid duplication of the Lodash library and makes sure that all imports | ||
from all packages are satisfied by the single global `lodash` module. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/** @format */ | ||
|
||
const types = require( 'babel-types' ); | ||
|
||
module.exports = function() { | ||
return { | ||
visitor: { | ||
ImportDeclaration( path ) { | ||
const { source } = path.node; | ||
|
||
// Transform any import from 'lodash-es' (exact match, no submodule) to 'lodash' | ||
const fullMatch = source.value.match( /^lodash-es$/ ); | ||
if ( fullMatch ) { | ||
source.value = 'lodash'; | ||
return; | ||
} | ||
|
||
// Transform default import from a 'lodash-es' submodule to a a named import from 'lodash' | ||
// Example: | ||
// In: import theGet from 'lodash-es/get' | ||
// Out: import { get as theGet } from 'lodash' | ||
const subMatch = source.value.match( /^lodash-es\/(.*)/ ); | ||
if ( subMatch ) { | ||
const { specifiers } = path.node; | ||
// If there is anything else than a single default import, throw an error. Such an | ||
// import is not valid. Example: import { get } from 'lodash-es/get' | ||
// There is only the default export in 'lodash-es/get' and no named one. | ||
if ( | ||
! specifiers || | ||
specifiers.length !== 1 || | ||
specifiers[ 0 ].type !== 'ImportDefaultSpecifier' | ||
) { | ||
throw path.buildCodeFrameError( | ||
'babel-lodash-es: Could not transform a non-default import from lodash-es/submodule' | ||
); | ||
} | ||
|
||
// Transforms | ||
// `import theGet from 'lodash-es/get'` | ||
// to | ||
// `import { get as theGet } from 'lodash'` | ||
const localIdentifier = specifiers[ 0 ].local; | ||
const importedIdentifier = types.identifier( subMatch[ 1 ] ); | ||
const specifier = types.importSpecifier( localIdentifier, importedIdentifier ); | ||
const declaration = types.importDeclaration( | ||
[ specifier ], | ||
types.stringLiteral( 'lodash' ) | ||
); | ||
path.replaceWith( declaration ); | ||
} | ||
}, | ||
}, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/** @format */ | ||
|
||
/** | ||
* External dependencies | ||
*/ | ||
const babel = require( 'babel-core' ); | ||
|
||
describe( 'babel-lodash-es', () => { | ||
function transform( code ) { | ||
return babel.transform( code, { | ||
plugins: [ require( '..' ) ], | ||
} ).code; | ||
} | ||
|
||
test( 'should transform named import from top-level package', () => { | ||
const code = transform( "import { get } from 'lodash-es';" ); | ||
expect( code ).toBe( "import { get } from 'lodash';" ); | ||
} ); | ||
|
||
test( 'should transform default import from top-level package', () => { | ||
const code = transform( "import _ from 'lodash-es';" ); | ||
expect( code ).toBe( "import _ from 'lodash';" ); | ||
} ); | ||
|
||
test( 'should transform default import from a submodule', () => { | ||
const code = transform( "import get from 'lodash-es/get'" ); | ||
expect( code ).toBe( "import { get } from 'lodash';" ); | ||
} ); | ||
|
||
test( 'should transform aliased default import from a submodule', () => { | ||
const code = transform( "import theGet from 'lodash-es/get';" ); | ||
expect( code ).toBe( "import { get as theGet } from 'lodash';" ); | ||
} ); | ||
|
||
test( 'should report error on a non-default import from a submodule', () => { | ||
const code = "import { get } from 'lodash-es/get'"; | ||
expect( () => transform( code ) ).toThrow( /Could not transform a non-default import/ ); | ||
} ); | ||
} ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters