├── .babelrc
├── .gitignore
├── .npmignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── package.json
├── source
└── index.js
└── test
├── fixtures
├── already-transformed
│ ├── actual.js
│ └── expected.js
├── mapped-members
│ ├── actual.js
│ └── expected.js
├── members
│ ├── actual.js
│ └── expected.js
├── mixed
│ ├── actual.js
│ └── expected.js
├── namespace
│ ├── actual.js
│ └── expected.js
├── no-specifier
│ ├── actual.js
│ └── expected.js
├── only-default
│ ├── actual.js
│ └── expected.js
└── unrelated
│ ├── actual.js
│ └── expected.js
└── index.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015"],
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | distribution/
2 | node_modules/
3 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | source/
2 | test/
3 | node_modules/
4 | .babelrc
5 | .gitignore
6 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | ## [1.0.2](https://github.com/nerdlabs/babel-plugin-transform-react-router-optimize/compare/v1.0.1...v1.0.2) (2017-09-04)
3 |
4 |
5 | ### Bug Fixes
6 |
7 | * **transform:** Map non-default named exports to the correct file ([3574c8c](https://github.com/nerdlabs/babel-plugin-transform-react-router-optimize/commit/3574c8c))
8 |
9 |
10 |
11 |
12 | ## [1.0.1](https://github.com/nerdlabs/babel-plugin-transform-react-router-optimize/compare/v1.0.0...v1.0.1) (2016-06-12)
13 |
14 |
15 | ### Bug Fixes
16 |
17 | * **transformation:** Leave imports which have no specifiers unchanged ([9a9738d](https://github.com/nerdlabs/babel-plugin-transform-react-router-optimize/commit/9a9738d))
18 |
19 |
20 |
21 |
22 | # 1.0.0 (2016-06-11)
23 |
24 |
25 | ### Features
26 |
27 | * **transform:** transform react-router imports ([ffbe2f0](https://github.com/nerdlabs/babel-plugin-transform-react-router-optimize/commit/ffbe2f0))
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 nerdlabs
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](http://commitizen.github.io/cz-cli/)
2 |
3 | # babel-plugin-transform-react-router-optimize
4 |
5 | The [React Router][0] library exposes all methods on the top level import, but
6 | allows developers to use imports referencing files directly inside `/lib`,
7 | which can result in smaller bundle sizes as it doesn't import all of the
8 | Router's dependencies.
9 |
10 | See here for more information: [Minimizing Bundle Size][1].
11 |
12 | This plugin can be added to your `.babelrc` file and automatically transform
13 | ES2015 imports to their size optimized counterpart.
14 |
15 | ## Example
16 | **In**
17 | ```javascript
18 | import { Route, IndexRoute } from 'react-router';
19 | ```
20 |
21 | **Out**
22 | ```javascript
23 | import Route from 'react-router/lib/Route';
24 | import IndexRoute from 'react-router/lib/IndexRoute';
25 | ```
26 |
27 | ## Installation
28 | **Note** This plugin is built for babel 6 and does not work with babel 5.
29 | ```sh
30 | npm install --save-dev babel-plugin-transform-react-router-optimize
31 | ```
32 |
33 | ## Usage
34 |
35 | ### Via `.babelrc` (recommended)
36 | **.babelrc**
37 | ```json
38 | {
39 | "plugins": ["transform-react-router-optimize"]
40 | }
41 | ```
42 |
43 | ### Via CLI
44 | ```sh
45 | babel --plugins transform-react-router-optimize script.js
46 | ```
47 |
48 | ### Via Node API
49 | ```javascript
50 | require('babel-core').transform('code', {
51 | plugins: ['transform-react-router-optimize']
52 | });
53 | ```
54 |
55 | ## License
56 |
57 | MIT
58 |
59 | [0]: https://github.com/reactjs/react-router/
60 | [1]: https://github.com/reactjs/react-router/blob/master/docs/guides/MinimizingBundleSize.md
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "babel-plugin-transform-react-router-optimize",
3 | "description": "Babel plugin to optimize the bundle size of projects using react-router.",
4 | "version": "1.0.2",
5 | "license": "MIT",
6 | "main": "distribution/index.js",
7 | "scripts": {
8 | "clean": "rm -rf distribution",
9 | "build": "babel -d distribution source",
10 | "test": "node test/index.js",
11 | "prepublish": "npm run clean && npm run build && npm run test"
12 | },
13 | "author": {
14 | "name": "Bjoern Brauer",
15 | "email": "zaubernerd@nerdlabs.it"
16 | },
17 | "config": {
18 | "commitizen": {
19 | "path": "cz-conventional-changelog-lint"
20 | }
21 | },
22 | "repository": {
23 | "type": "git",
24 | "url": "git+https://github.com/nerdlabs/babel-plugin-transform-react-router-optimize.git"
25 | },
26 | "bugs": {
27 | "url": "https://github.com/nerdlabs/babel-plugin-transform-react-router-optimize/issues"
28 | },
29 | "homepage": "https://github.com/nerdlabs/babel-plugin-transform-react-router-optimize#readme",
30 | "keywords": [
31 | "babel-plugin",
32 | "react-router",
33 | "optimization",
34 | "minify",
35 | "react",
36 | "reactjs"
37 | ],
38 | "devDependencies": {
39 | "babel-cli": "^6.10.1",
40 | "babel-core": "^6.9.1",
41 | "babel-preset-es2015": "^6.9.0",
42 | "chalk": "^1.1.3",
43 | "cz-conventional-changelog-lint": "^0.1.3",
44 | "diff": "^2.2.3"
45 | },
46 | "peerDependencies": {
47 | "react-router": ">=2.0.0"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/source/index.js:
--------------------------------------------------------------------------------
1 | export default function ({types: t}) {
2 | const namespace = 'react-router/lib'
3 | const importMap = {
4 | createRoutes: 'RouteUtils',
5 | locationShape: 'PropTypes',
6 | routerShape: 'PropTypes',
7 | formatPattern: 'PatternUtils'
8 | }
9 |
10 | const canReplace = ({ specifiers }) => {
11 | return specifiers.length > 0 && specifiers.every((specifier) => {
12 | return t.isImportSpecifier(specifier)
13 | && specifier.imported.name !== 'default';
14 | });
15 | };
16 |
17 | const replace = (specifiers) => {
18 | return specifiers.map(({local, imported}) => {
19 | const mapped = importMap[imported.name]
20 |
21 | if (typeof mapped !== 'undefined') {
22 | return t.importDeclaration(
23 | [t.importSpecifier(local, imported)],
24 | t.stringLiteral(`${namespace}/${mapped}`)
25 | );
26 | }
27 |
28 | return t.importDeclaration(
29 | [t.importDefaultSpecifier(local)],
30 | t.stringLiteral(`${namespace}/${imported.name}`)
31 | );
32 | });
33 | };
34 |
35 | return {
36 | visitor: {
37 | ImportDeclaration(path) {
38 | if (path.node.source.value === 'react-router') {
39 | if (canReplace(path.node)) {
40 | path.replaceWithMultiple(replace(path.node.specifiers));
41 | }
42 | }
43 | }
44 | }
45 | };
46 | }
47 |
--------------------------------------------------------------------------------
/test/fixtures/already-transformed/actual.js:
--------------------------------------------------------------------------------
1 | import member from 'react-router/lib/member';
2 |
--------------------------------------------------------------------------------
/test/fixtures/already-transformed/expected.js:
--------------------------------------------------------------------------------
1 | import member from 'react-router/lib/member';
2 |
--------------------------------------------------------------------------------
/test/fixtures/mapped-members/actual.js:
--------------------------------------------------------------------------------
1 | import { createRoutes, locationShape, routerShape } from 'react-router';
2 | import { formatPattern as format } from 'react-router';
3 |
--------------------------------------------------------------------------------
/test/fixtures/mapped-members/expected.js:
--------------------------------------------------------------------------------
1 | import { createRoutes } from 'react-router/lib/RouteUtils';
2 | import { locationShape } from 'react-router/lib/PropTypes';
3 | import { routerShape } from 'react-router/lib/PropTypes';
4 | import { formatPattern as format } from 'react-router/lib/PatternUtils';
5 |
--------------------------------------------------------------------------------
/test/fixtures/members/actual.js:
--------------------------------------------------------------------------------
1 | import { member } from 'react-router';
2 | import { member as alias } from 'react-router';
3 | import { member1 , member2 } from 'react-router';
4 | import { member3 , member2 as alias2 } from 'react-router';
5 |
--------------------------------------------------------------------------------
/test/fixtures/members/expected.js:
--------------------------------------------------------------------------------
1 | import member from 'react-router/lib/member';
2 | import alias from 'react-router/lib/member';
3 | import member1 from 'react-router/lib/member1';
4 | import member2 from 'react-router/lib/member2';
5 | import member3 from 'react-router/lib/member3';
6 | import alias2 from 'react-router/lib/member2';
7 |
--------------------------------------------------------------------------------
/test/fixtures/mixed/actual.js:
--------------------------------------------------------------------------------
1 | import Router, { member } from 'react-router';
2 |
--------------------------------------------------------------------------------
/test/fixtures/mixed/expected.js:
--------------------------------------------------------------------------------
1 | import Router, { member } from 'react-router';
2 |
--------------------------------------------------------------------------------
/test/fixtures/namespace/actual.js:
--------------------------------------------------------------------------------
1 | import * as Router from 'react-router';
2 |
--------------------------------------------------------------------------------
/test/fixtures/namespace/expected.js:
--------------------------------------------------------------------------------
1 | import * as Router from 'react-router';
2 |
--------------------------------------------------------------------------------
/test/fixtures/no-specifier/actual.js:
--------------------------------------------------------------------------------
1 | import 'react-router';
2 |
--------------------------------------------------------------------------------
/test/fixtures/no-specifier/expected.js:
--------------------------------------------------------------------------------
1 | import 'react-router';
2 |
--------------------------------------------------------------------------------
/test/fixtures/only-default/actual.js:
--------------------------------------------------------------------------------
1 | import Router from 'react-router';
2 |
--------------------------------------------------------------------------------
/test/fixtures/only-default/expected.js:
--------------------------------------------------------------------------------
1 | import Router from 'react-router';
2 |
--------------------------------------------------------------------------------
/test/fixtures/unrelated/actual.js:
--------------------------------------------------------------------------------
1 | import { A, B } from 'react';
2 |
--------------------------------------------------------------------------------
/test/fixtures/unrelated/expected.js:
--------------------------------------------------------------------------------
1 | import { A, B } from 'react';
2 |
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 | const assert = require('assert');
2 | const babel = require('babel-core');
3 | const chalk = require('chalk');
4 | const diff = require('diff');
5 | const fs = require('fs');
6 | const path = require('path');
7 |
8 | const pluginPath = require.resolve('../distribution/index.js');
9 |
10 | function runTests() {
11 | const testsPath = __dirname + '/fixtures/';
12 |
13 | fs.readdirSync(testsPath)
14 | .map((item) => ({ path: path.join(testsPath, item), name: item }))
15 | .filter((item) => fs.statSync(item.path).isDirectory())
16 | .forEach(runTest);
17 | }
18 |
19 | function runTest(dir) {
20 | const actual = babel.transformFileSync(dir.path + '/actual.js', {
21 | plugins: [pluginPath],
22 | babelrc: false
23 | });
24 |
25 | const expected = fs.readFileSync(dir.path + '/expected.js', 'utf-8');
26 |
27 | function normalizeLines(str) {
28 | return str.trimRight().replace(/\r\n/g, '\n');
29 | }
30 |
31 | process.stdout.write(chalk.bgWhite.black(dir.name));
32 | process.stdout.write('\n\n');
33 |
34 | diff.diffLines(normalizeLines(expected), normalizeLines(actual.code))
35 | .forEach((part) => {
36 | const colorize = part.added ? chalk.green :
37 | part.removed ? chalk.red : chalk.grey;
38 |
39 | process.stdout.write(colorize(part.value.trim()) + '\n');
40 | });
41 |
42 | assert.equal(normalizeLines(expected), normalizeLines(actual.code));
43 |
44 | process.stdout.write('\n\n\n');
45 | }
46 |
47 |
48 | runTests();
--------------------------------------------------------------------------------