├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .npmignore ├── .npmrc ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── package.json ├── src └── index.js └── test ├── .eslintrc ├── fixtures ├── basic-import │ ├── actual.js │ └── expected.js ├── chained-import │ ├── actual.js │ └── expected.js ├── dynamic-argument │ ├── actual.js │ └── expected.js └── nested-import │ ├── actual.js │ └── expected.js ├── index.js └── testPlugin.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "airbnb" 4 | ], 5 | } 6 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | test/fixtures 2 | lib/ 3 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": "airbnb-base", 4 | "root": true 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | # Build library 40 | lib/ 41 | 42 | # Only apps should have lockfiles 43 | npm-shrinkwrap.json 44 | package-lock.json 45 | yarn.lock 46 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | test/ 3 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | os: 3 | - linux 4 | node_js: 5 | - "10" 6 | - "8" 7 | - "6" 8 | - "4" 9 | before_install: 10 | - 'nvm install-latest-npm' 11 | install: 12 | - 'if [ "${TRAVIS_NODE_VERSION}" = "0.6" ] || [ "${TRAVIS_NODE_VERSION}" = "0.9" ]; then nvm install --latest-npm 0.8 && npm install && nvm use "${TRAVIS_NODE_VERSION}"; else npm install; fi;' 13 | script: 14 | - 'if [ -n "${PRETEST-}" ]; then npm run pretest ; fi' 15 | - 'if [ -n "${POSTTEST-}" ]; then npm run posttest ; fi' 16 | - 'if [ -n "${COVERAGE-}" ]; then npm run coverage ; fi' 17 | - 'if [ -n "${TEST-}" ]; then npm run tests-only ; fi' 18 | sudo: false 19 | env: 20 | - TEST=true 21 | matrix: 22 | fast_finish: true 23 | include: 24 | - node_js: "lts/*" 25 | env: PRETEST=true 26 | allow_failures: 27 | - env: COVERAGE=true 28 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## v1.1.0 2 | 3 | - [New] Removes dependency on babel-template and babel-plugin-syntax-dynamic-import ([#51](https://github.com/airbnb/babel-plugin-dynamic-import-webpack/pull/51)) 4 | 5 | ## v1.0.2 6 | 7 | - [refactor] Visit Import nodes instead of CallExpressions ([#33](https://github.com/airbnb/babel-plugin-dynamic-import-webpack/pull/33)) 8 | 9 | ## v1.0.1 10 | 11 | - [patch] Added automatic syntax support. You no longer need to add the `syntax-dynamic-import` plugin to your babel configuration. ([#5](https://github.com/airbnb/babel-plugin-dynamic-import-webpack/pull/5)) 12 | 13 | ## v1.0.0 14 | 15 | - Initial full release. 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Airbnb 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 | | :exclamation: Deprecation Notice | 2 | |:-| 3 | |We want to express our sincere gratitude for your support and contributions to this open source project. As we are no longer using this technology internally, we have come to the decision to archive this repository. While we won't be providing further updates or support, the existing code and resources will remain accessible for your reference. We encourage anyone interested to fork the repository and continue the project's legacy independently. Thank you for being a part of this journey and for your patience and understanding.| 4 | 5 | # babel-plugin-dynamic-import-webpack 6 | 7 | Babel plugin to transpile `import()` to `require.ensure`, for Webpack. 8 | 9 | Note that Webpack 2 has [gotten `import()`](https://github.com/webpack/webpack/issues/3098) after this code was written. 10 | 11 | **NOTE:** Babylon v6.12.0 is required to correctly parse dynamic imports. 12 | 13 | ## Installation 14 | 15 | ```sh 16 | $ npm install babel-plugin-dynamic-import-webpack --save-dev 17 | ``` 18 | 19 | ## Usage 20 | 21 | ### Via `.babelrc` (Recommended) 22 | 23 | **.babelrc** 24 | 25 | ```json 26 | { 27 | "plugins": ["dynamic-import-webpack"] 28 | } 29 | ``` 30 | 31 | ### Via CLI 32 | 33 | ```sh 34 | $ babel --plugins dynamic-import-webpack script.js 35 | ``` 36 | 37 | ### Via Node API 38 | 39 | ```javascript 40 | require("babel-core").transform("code", { 41 | plugins: ["dynamic-import-webpack"] 42 | }); 43 | ``` 44 | 45 | ### Dynamic imports and webpack 46 | 47 | Although the specification for `import()` supports a dynamic importing of modules in the browser runtime, webpack's `require.ensure()` is not dynamic and requires a hardcoded string to work correctly. For more information see [webpack's documentation](https://webpack.js.org/guides/code-splitting/#dynamic-imports) on dynamic imports. 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "babel-plugin-dynamic-import-webpack", 3 | "version": "1.1.0", 4 | "description": "Babel plugin to transpile import() to require.ensure, for Webpack", 5 | "main": "lib/index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "clean": "rimraf lib", 11 | "prebuild": "npm run clean", 12 | "build": "babel src --out-dir lib", 13 | "pretest": "npm run lint", 14 | "test": "npm run tests-only", 15 | "tests-only": "tape --require babel-register test", 16 | "lint": "eslint .", 17 | "prepublish": "in-publish && safe-publish-latest && npm run build || not-in-publish", 18 | "check-changelog": "expr $(git status --porcelain 2>/dev/null| grep \"^\\s*M.*CHANGELOG.md\" | wc -l) >/dev/null || (echo 'Please edit CHANGELOG.md' && exit 1)", 19 | "check-only-changelog-changed": "(expr $(git status --porcelain 2>/dev/null| grep -v \"CHANGELOG.md\" | wc -l) >/dev/null && echo 'Only CHANGELOG.md may have uncommitted changes' && exit 1) || exit 0", 20 | "version:major": "npm --no-git-tag-version version major", 21 | "version:minor": "npm --no-git-tag-version version minor", 22 | "version:patch": "npm --no-git-tag-version version patch", 23 | "postversion": "git commit package.json CHANGELOG.md -m \"v$npm_package_version\" && npm run tag && git push && git push --tags", 24 | "preversion": "npm run test && npm run check-changelog && npm run check-only-changelog-changed", 25 | "tag": "git tag v$npm_package_version" 26 | }, 27 | "repository": { 28 | "type": "git", 29 | "url": "git+https://github.com/airbnb/babel-plugin-dynamic-import-webpack.git" 30 | }, 31 | "keywords": [ 32 | "babel", 33 | "plugin", 34 | "dynamic", 35 | "import", 36 | "webpack" 37 | ], 38 | "author": "Jordan Gensler ", 39 | "license": "MIT", 40 | "bugs": { 41 | "url": "https://github.com/airbnb/babel-plugin-dynamic-import-webpack/issues" 42 | }, 43 | "homepage": "https://github.com/airbnb/babel-plugin-dynamic-import-webpack#readme", 44 | "devDependencies": { 45 | "babel-cli": "^6.26.0", 46 | "babel-core": "^6.26.3", 47 | "babel-eslint": "^8.2.3", 48 | "babel-preset-airbnb": "^2.4.0", 49 | "babel-register": "^6.26.0", 50 | "eslint": "^4.19.1", 51 | "eslint-config-airbnb-base": "^12.1.0", 52 | "eslint-plugin-import": "^2.12.0", 53 | "in-publish": "^2.0.0", 54 | "rimraf": "^2.6.2", 55 | "safe-publish-latest": "^1.1.1", 56 | "tape": "^4.9.0" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export default ({ template }) => { 2 | const buildImport = template(` 3 | (new Promise((resolve) => { 4 | require.ensure([], (require) => { 5 | resolve(require(SOURCE)); 6 | }); 7 | })) 8 | `); 9 | 10 | return { 11 | // NOTE: Once we drop support for Babel <= v6 we should 12 | // update this to import from @babel/plugin-syntax-dynamic-import. 13 | // https://www.npmjs.com/package/@babel/plugin-syntax-dynamic-import 14 | manipulateOptions(opts, parserOpts) { 15 | parserOpts.plugins.push('dynamicImport'); 16 | }, 17 | visitor: { 18 | Import(path) { 19 | const newImport = buildImport({ 20 | SOURCE: path.parentPath.node.arguments, 21 | }); 22 | path.parentPath.replaceWith(newImport); 23 | }, 24 | }, 25 | }; 26 | }; 27 | -------------------------------------------------------------------------------- /test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true, 4 | }, 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/basic-import/actual.js: -------------------------------------------------------------------------------- 1 | const testModule = import('test-module'); 2 | -------------------------------------------------------------------------------- /test/fixtures/basic-import/expected.js: -------------------------------------------------------------------------------- 1 | const testModule = new Promise(resolve => { 2 | require.ensure([], require => { 3 | resolve(require('test-module')); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /test/fixtures/chained-import/actual.js: -------------------------------------------------------------------------------- 1 | import('test-module').then(() => ( 2 | import('test-module-2') 3 | )); 4 | 5 | Promise.all([ 6 | import('test-1'), 7 | import('test-2'), 8 | import('test-3'), 9 | ]).then(() => {}); 10 | -------------------------------------------------------------------------------- /test/fixtures/chained-import/expected.js: -------------------------------------------------------------------------------- 1 | new Promise(resolve => { 2 | require.ensure([], require => { 3 | resolve(require('test-module')); 4 | }); 5 | }).then(() => new Promise(resolve => { 6 | require.ensure([], require => { 7 | resolve(require('test-module-2')); 8 | }); 9 | })); 10 | 11 | Promise.all([new Promise(resolve => { 12 | require.ensure([], require => { 13 | resolve(require('test-1')); 14 | }); 15 | }), new Promise(resolve => { 16 | require.ensure([], require => { 17 | resolve(require('test-2')); 18 | }); 19 | }), new Promise(resolve => { 20 | require.ensure([], require => { 21 | resolve(require('test-3')); 22 | }); 23 | })]).then(() => {}); 24 | -------------------------------------------------------------------------------- /test/fixtures/dynamic-argument/actual.js: -------------------------------------------------------------------------------- 1 | const MODULE = 'test-module'; 2 | 3 | import(MODULE); 4 | import(`test-${MODULE}`); 5 | -------------------------------------------------------------------------------- /test/fixtures/dynamic-argument/expected.js: -------------------------------------------------------------------------------- 1 | const MODULE = 'test-module'; 2 | 3 | new Promise(resolve => { 4 | require.ensure([], require => { 5 | resolve(require(MODULE)); 6 | }); 7 | }); 8 | new Promise(resolve => { 9 | require.ensure([], require => { 10 | resolve(require(`test-${MODULE}`)); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/fixtures/nested-import/actual.js: -------------------------------------------------------------------------------- 1 | function getModule(path) { 2 | return import('test-module'); 3 | } 4 | 5 | getModule().then(() => {}); 6 | -------------------------------------------------------------------------------- /test/fixtures/nested-import/expected.js: -------------------------------------------------------------------------------- 1 | function getModule(path) { 2 | return new Promise(resolve => { 3 | require.ensure([], require => { 4 | resolve(require('test-module')); 5 | }); 6 | }); 7 | } 8 | 9 | getModule().then(() => {}); 10 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | import test from 'tape'; 2 | import { join } from 'path'; 3 | import { readdirSync, statSync, readFileSync } from 'fs'; 4 | 5 | import testPlugin from './testPlugin'; 6 | 7 | const FIXTURE_PATH = join(__dirname, 'fixtures'); 8 | 9 | const testFolders = readdirSync(FIXTURE_PATH).filter(file => ( 10 | statSync(join(FIXTURE_PATH, file)).isDirectory() 11 | )); 12 | 13 | test('babel-plugin-dynamic-import-webpack', (t) => { 14 | testFolders.forEach((folderName) => { 15 | const actual = readFileSync(join(FIXTURE_PATH, folderName, 'actual.js'), 'utf8'); 16 | const expected = readFileSync(join(FIXTURE_PATH, folderName, 'expected.js'), 'utf8'); 17 | t.test(`works with ${folderName}`, (st) => { 18 | const result = testPlugin(actual); 19 | st.equal(result.trim(), expected.trim()); 20 | st.end(); 21 | }); 22 | }); 23 | 24 | t.end(); 25 | }); 26 | -------------------------------------------------------------------------------- /test/testPlugin.js: -------------------------------------------------------------------------------- 1 | import { transform } from 'babel-core'; 2 | 3 | export default function testPlugin(code) { 4 | const result = transform(code, { 5 | plugins: ['./src/index.js'], 6 | }); 7 | 8 | return result.code; 9 | } 10 | --------------------------------------------------------------------------------