├── .codeclimate.yml ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .github └── CODEOWNERS ├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── __tests__ ├── __snapshots__ │ └── index.test.js.snap └── index.test.js ├── index.js ├── package.json ├── renovate.json ├── screenshot.png ├── universal-graphic.png ├── universalImport.js ├── wallaby.js └── yarn.lock /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | languages: 2 | JavaScript: true 3 | 4 | engines: 5 | duplication: 6 | enabled: true 7 | config: 8 | languages: 9 | - javascript: 10 | fixme: 11 | enabled: true 12 | eslint: 13 | enabled: true 14 | config: 15 | config: .eslintrc.js 16 | checks: 17 | import/no-unresolved: 18 | enabled: false 19 | import/extensions: 20 | enabled: false 21 | 22 | ratings: 23 | paths: 24 | - "index.js" 25 | - "importCss.js" 26 | - "universalImport.js" 27 | 28 | exclude_paths: 29 | - "docs/" 30 | - "dist/" 31 | - "flow-typed/" 32 | - "node_modules/" 33 | - ".vscode/" 34 | - ".eslintrc.js" 35 | - "**/*.snap" 36 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | [*] 3 | indent_style = space 4 | indent_size = 2 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | [*.md] 10 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | flow-typed 3 | node_modules 4 | docs 5 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: 'babel-eslint', 3 | parserOptions: { 4 | ecmaFeatures: { 5 | generators: true, 6 | experimentalObjectRestSpread: true 7 | }, 8 | sourceType: 'module', 9 | allowImportExportEverywhere: false 10 | }, 11 | plugins: ['flowtype'], 12 | extends: ['airbnb', 'plugin:flowtype/recommended'], 13 | settings: { 14 | flowtype: { 15 | onlyFilesWithFlowAnnotation: true 16 | }, 17 | 'import/resolver': { 18 | node: { 19 | extensions: ['.js', '.json', '.css', '.styl'] 20 | } 21 | } 22 | }, 23 | globals: { 24 | window: true, 25 | document: true, 26 | __dirname: true, 27 | __DEV__: true, 28 | CONFIG: true, 29 | process: true, 30 | jest: true, 31 | describe: true, 32 | test: true, 33 | it: true, 34 | expect: true, 35 | beforeEach: true, 36 | fetch: true, 37 | alert: true 38 | }, 39 | rules: { 40 | quotes: ['error', 'single', { allowTemplateLiterals: true }], 41 | 'import/extensions': [ 42 | 'error', 43 | 'always', 44 | { 45 | js: 'never', 46 | jsx: 'never', 47 | styl: 'never', 48 | css: 'never' 49 | } 50 | ], 51 | 'no-shadow': 0, 52 | 'no-use-before-define': 0, 53 | 'no-param-reassign': 0, 54 | 'react/prop-types': 0, 55 | 'react/no-render-return-value': 0, 56 | 'no-confusing-arrow': 0, 57 | 'no-underscore-dangle': 0, 58 | 'no-plusplus': 0, 59 | camelcase: 1, 60 | 'prefer-template': 1, 61 | 'react/no-array-index-key': 1, 62 | 'global-require': 1, 63 | 'react/jsx-indent': 1, 64 | 'dot-notation': 1, 65 | 'import/no-named-default': 1, 66 | 'no-unused-vars': 1, 67 | 'flowtype/no-weak-types': 1, 68 | 'consistent-return': 1, 69 | 'import/prefer-default-export': 1, 70 | 'no-console': 1, 71 | 'jsx-a11y/no-static-element-interactions': 1, 72 | 'no-case-declarations': 1, 73 | 'no-template-curly-in-string': 1, 74 | 'no-return-assign': 1, 75 | 'no-multi-assign': 1, 76 | semi: [2, 'never'], 77 | 'flowtype/semi': [2, 'never'], 78 | 'jsx-quotes': [2, 'prefer-single'], 79 | 'react/jsx-filename-extension': [2, { extensions: ['.jsx', '.js'] }], 80 | 'spaced-comment': [2, 'always', { markers: ['?'] }], 81 | 'arrow-parens': [2, 'as-needed', { requireForBlockBody: false }], 82 | 'brace-style': [2, 'stroustrup'], 83 | 'import/no-unresolved': [2, { commonjs: true, caseSensitive: true }], 84 | 'no-unused-expressions': [ 85 | 1, 86 | { 87 | allowShortCircuit: true, 88 | allowTernary: true, 89 | allowTaggedTemplates: true 90 | } 91 | ], 92 | 'import/no-extraneous-dependencies': [ 93 | 'error', 94 | { 95 | devDependencies: true, 96 | optionalDependencies: true, 97 | peerDependencies: true 98 | } 99 | ], 100 | 'comma-dangle': [ 101 | 2, 102 | { 103 | arrays: 'never', 104 | objects: 'never', 105 | imports: 'never', 106 | exports: 'never', 107 | functions: 'never' 108 | } 109 | ], 110 | 'max-len': [ 111 | 'error', 112 | { 113 | code: 80, 114 | tabWidth: 2, 115 | ignoreUrls: true, 116 | ignoreComments: true, 117 | ignoreRegExpLiterals: true, 118 | ignoreStrings: true, 119 | ignoreTemplateLiterals: true 120 | } 121 | ], 122 | 'react/sort-comp': [ 123 | 2, 124 | { 125 | order: [ 126 | 'propTypes', 127 | 'props', 128 | 'state', 129 | 'defaultProps', 130 | 'contextTypes', 131 | 'childContextTypes', 132 | 'getChildContext', 133 | 'static-methods', 134 | 'lifecycle', 135 | 'everything-else', 136 | 'render' 137 | ] 138 | } 139 | ] 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # babel-plugin-universal-import maintainers 2 | * @ScriptedAlchemy 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | coverage 3 | node_modules 4 | *.log 5 | .idea 6 | .DS_Store 7 | yarn-error.log 8 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | __tests__ 3 | __test-helpers__ 4 | .vscode 5 | *.log 6 | src 7 | .babelrc 8 | .codeclimate.yml 9 | .editorconfig 10 | .eslintrc.js 11 | .snyk 12 | .github 13 | .travis.yml 14 | wallaby.js 15 | webpack.config.js 16 | yarn-error.log 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - stable 4 | cache: yarn 5 | script: 6 | - node_modules/.bin/travis-github-status lint jest codeclimate 7 | notifications: 8 | email: false 9 | webhooks: 10 | urls: 11 | - https://webhooks.gitter.im/e/5156be73e058008e1ed2 12 | on_success: always # options: [always|never|change] default: always 13 | on_failure: always # options: [always|never|change] default: always 14 | on_start: never # options: [always|never|change] default: always 15 | after_success: 16 | - npm run semantic-release 17 | branches: 18 | except: 19 | - /^v\d+\.\d+\.\d+$/ 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-present James Gillmore 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Reactlandia Chat 3 | 4 | 5 | # babel-plugin-universal-import 6 | 7 |

8 | 9 | Version 10 | 11 | 12 | 13 | Build Status 14 | 15 | 16 | 17 | Coverage Status 18 | 19 | 20 | 21 | Green Keeper 22 | 23 | 24 | 25 | GPA 26 | 27 | 28 | 29 | Downloads 30 | 31 | 32 | 33 | License 34 | 35 |

36 | 37 | 38 |

39 | 40 |

41 | 42 | ## Installation 43 | ``` 44 | yarn add babel-plugin-universal-import 45 | ``` 46 | *.babelrc:* 47 | ```js 48 | { 49 | "plugins": ["universal-import"] 50 | } 51 | ``` 52 | 53 | 54 | ## What it does 55 | Taking from the [test snapshots](./__tests__/__snapshots__/index.js.snap), it does this: 56 | 57 | ```js 58 | import universal from 'react-universal-component' 59 | const UniversalComponent = universal(import('./Foo.js')) 60 | 61 | 62 | 63 | ↓ ↓ ↓ ↓ ↓ ↓ 64 | 65 | import universal from 'react-universal-component' 66 | import universalImport from 'babel-plugin-universal-import/universalImport.js' 67 | import path from 'path' 68 | 69 | const UniversalComponent = universal(universalImport({ 70 | chunkName: () => 'Foo', 71 | path: () => path.join(__dirname, './Foo.js'), 72 | resolve: () => require.resolveWeak('./Foo.js'), 73 | load: () => Promise.all([ 74 | import( /* webpackChunkName: 'Foo' */ './Foo.js') 75 | ]).then(proms => proms[0]) 76 | })) 77 | 78 | 79 | ``` 80 | 81 | And if you're using dynamic imports: 82 | 83 | ```js 84 | import universal from 'react-universal-component' 85 | const UniversalComponent = universal(props => import(`./${props.page}`)) 86 | 87 | 88 | 89 | ↓ ↓ ↓ ↓ ↓ ↓ 90 | 91 | import universal from 'react-universal-component' 92 | import universalImport from 'babel-plugin-universal-import/universalImport.js' 93 | import path from 'path' 94 | 95 | const UniversalComponent = universal(props => universalImport({ 96 | chunkName: props => props.page, 97 | path: props => path.join(__dirname, `./${props.page}`), 98 | resolve: props => require.resolveWeak(`./${props.page}`), 99 | load: props => Promise.all([ 100 | import( /* webpackChunkName: '[request]' */ `./${props.page}`) 101 | ]).then(proms => proms[0]) 102 | })); 103 | 104 | 105 | ``` 106 | > NOTE: if you aren't using `react-universal-component` and you just want to serve CSS chunks from [extract-css-chunks-webpack-plugin](https://github.com/faceyspacey/extract-css-chunks-webpack-plugin), its not a problem! extract-css-chunks is completely standalone and fully HMR 107 | 108 | It names all your chunks using *magic comments* (see webpack documentation on [magic comments](https://webpack.js.org/api/module-methods/#import-)) 🔮 behind the scenes and is derived from the imported file. This works with both static and dynamic import paths, as you can see above. 109 | 110 | Otherwise, what it's doing is providing all the different types of requires/paths/imports/etc needed by tools like [react-universal-component](https://github.com/faceyspacey/react-universal-component) to universally render your component. 111 | 112 | The targeted **use-case** for all this is dynamic imports where you can pass a `page` prop to the resulting component, thereby allowing you to create one `` for a large number of your components. This is a major upgrade to the previous way of having to make a hash of a million async components in a wrapping component. You no longer have to think about *Universal Components* as anything different than your other components that use simple HoCs. 113 | 114 | 115 | And maybe even *cooler* to some: you don't have to do `universal(() => import())`. I.e. you don't have to wrap it in a function any longer when using `react-universal-component`, similar to `dynamic(import())` in Next.js...*unless of course you're making use of the extremely useful `props` argument.* 116 | 117 | ## Typescript and non-Babel environments 118 | 119 | If you can't use babel, you can either copy what this plugin does above, or you can do a shorter version where you just put the important configuration key/vals on the 2nd options argument to `universal`: 120 | 121 | ```js 122 | import universal from 'react-universal-component' 123 | 124 | const load = props => Promise.all([ 125 | import( /* webpackChunkName: '[request]' */ `./${props.page}`) 126 | ]).then(proms => proms[0]) 127 | 128 | const UniversalComponent = universal(load, { 129 | chunkName: props => props.page, 130 | resolve: props => require.resolveWeak(`./${props.page}`) 131 | }); 132 | ``` 133 | > notice `chunkName` and `resolve` as standard options on the 2nd options argument. 134 | 135 | ## Babel Server Or Webpack < 2.2.20 136 | 137 | If your compiling the server with Babel, set the following option so `import()` does not exist in the final compilation result server-side: 138 | 139 | ```js 140 | { 141 | "plugins": [ 142 | ["universal-import", { 143 | "babelServer": true 144 | }] 145 | ] 146 | } 147 | ``` 148 | 149 | ## Include additional debugging info 150 | To prevent leaking of information, file names are not included in the final output. However, for debugging purposes, you may set the `includeFileName` flag option to true. This will include the path to the source file from which the import() is happening to be exposed. 151 | 152 | ```js 153 | { 154 | "plugins": [ 155 | ["universal-import", { 156 | "includeFileName": true 157 | }] 158 | ] 159 | } 160 | ``` 161 | 162 | ## Advanced magic comments 163 | This plugin supports currying of the following magic comments defiend by Webpack to the transpiled output: 164 | 165 | - `webpackMode` 166 | - `webpackInclude` 167 | - `webpackExclude` 168 | - `webpackIgnore` 169 | - `webpackPreload` 170 | - `webpackPrefetch` 171 | 172 | In order to pass that on to the output, you must provide each magic comment in it's own comment block, e.g. 173 | 174 | ```javascript 175 | import( 176 | /* webpackMode: "lazy" */ 177 | /* webpackChunkName: "Foo" */ 178 | "./Foo" 179 | ) 180 | ``` 181 | 182 | Order in which you specify them will not matter, and invalid leading comments will be stripped out. The logic for naming your webpack chunks remains the same if you specify any of these advanced options. Please refer to the [webpack documentation](https://webpack.js.org/api/module-methods/#import-) for valid values and configurations of each of these settings. 183 | 184 | 185 | ## Next Steps 186 | 187 | Checkout the rest of the packages in the *"Universal"* family: 188 | - [webpack-flush-chunks](https://github.com/faceyspacey/webpack-flush-chunks) 189 | - [react-universal-component](https://github.com/faceyspacey/react-universal-component) 190 | - [extract-css-chunks-webpack-plugin](https://github.com/faceyspacey/extract-css-chunks-webpack-plugin) 191 | 192 | ## Caveat 193 | - For chunks to be properly created--and since their names are automatically generated for you--you can't have different chunks with the same name, say `index`. So instead of ```import(`./index`)```, make your imports like this: ```import(`../ComponentFolderA`)``` and ```import(`../ComponentFolderB`)```. Notice you're going back one directory--this allows the chunk name to be generated uniquely even though the entry point file is `index.js` for both components. In addition, if in multiple places you import the same module, make sure they both start with the same base directory name. **Again, using `..` is your friend. Initial dots and slashes will be stripped from the resulting chunk name.** 194 | 195 | - To the discerning eye, you may be wondering if the return of `import()` is still *thenable*?? It is! However, if you don't call `.then` on it, somewhere (perhaps in the components like *react-universal-component* that you pass it to), then it won't perform the import. Since most of us are using modules, which we need to do something with in the `then` callback, that's not a problem. But if you happen to be importing a module that does its own setup, such as attaches something to the `window` object, well then you just need to call `.then()` to trigger it. That's a rare case these days, which is why we decided to go with the simplicity seen here. And yes, async await works too. 196 | 197 | ## Contributing 198 | 199 | We use [commitizen](https://github.com/commitizen/cz-cli), so run `npm run cm` to make commits. A command-line form will appear, requiring you answer a few questions to automatically produce a nicely formatted commit. Releases, semantic version numbers, tags, changelogs and publishing to NPM will automatically be handled based on these commits thanks to [semantic-release](https://github.com/semantic-release/semantic-release). Be good. 200 | 201 | 202 | ## Tests 203 | 204 | Reviewing a package's tests are a great way to get familiar with it. It's direct insight into the capabilities of the given package (if the tests are thorough). What's even better is a screenshot of the tests neatly organized and grouped (you know the whole "a picture says a thousand words" thing). 205 | 206 | Below is a screenshot of this module's tests running in [Wallaby](https://wallabyjs.com) *("An Integrated Continuous Testing Tool for JavaScript")* which everyone in the React community should be using. It's fantastic and has taken my entire workflow to the next level. It re-runs your tests on every change along with comprehensive logging, bi-directional linking to your IDE, in-line code coverage indicators, **and even snapshot comparisons + updates for Jest!** I requestsed that feature by the way :). It's basically a substitute for live-coding that inspires you to test along your journey. 207 | 208 | 209 | ![babel-plugin-universal-import screenshot](./screenshot.png) 210 | 211 | ## More from FaceySpacey in Reactlandia 212 | - [redux-first-router](https://github.com/faceyspacey/redux-first-router). It's made to work perfectly with *Universal*. Together they comprise our *"frameworkless"* Redux-based approach to what Next.js does (splitting, SSR, prefetching, routing). 213 | -------------------------------------------------------------------------------- /__tests__/__snapshots__/index.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`await import() should receive a thennable without calling .then 1`] = ` 4 | " 5 | async ({ page }) => await import(\`../components/\${page}\`); 6 | 7 | ↓ ↓ ↓ ↓ ↓ ↓ 8 | 9 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 10 | 11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 12 | 13 | async ({ 14 | page 15 | }) => await (0, _universalImport2.default)(() => Promise.all([import( 16 | /* webpackChunkName: 'components/[request]' */ 17 | \`../components/\${page}\`)]).then(proms => proms[0]), false); 18 | " 19 | `; 20 | 21 | exports[`babelServer: true 1`] = ` 22 | " 23 | import(\\"./Foo\\") 24 | 25 | ↓ ↓ ↓ ↓ ↓ ↓ 26 | 27 | var _path2 = _interopRequireDefault(require(\\"path\\")); 28 | 29 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 30 | 31 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 32 | 33 | (0, _universalImport2.default)({ 34 | id: \\"./Foo\\", 35 | path: () => _path2.default.join(__dirname, \\"./Foo\\"), 36 | resolve: () => require.resolveWeak(\\"./Foo\\"), 37 | chunkName: () => \\"Foo\\" 38 | }); 39 | " 40 | `; 41 | 42 | exports[`disableWarnings: true 1`] = ` 43 | " 44 | import(\\"./Foo\\") 45 | 46 | ↓ ↓ ↓ ↓ ↓ ↓ 47 | 48 | var _path2 = _interopRequireDefault(require(\\"path\\")); 49 | 50 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 51 | 52 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 53 | 54 | (0, _universalImport2.default)({ 55 | id: \\"./Foo\\", 56 | load: () => Promise.all([import( 57 | /* webpackChunkName: 'Foo' */ 58 | \\"./Foo\\")]).then(proms => proms[0]), 59 | path: () => _path2.default.join(__dirname, \\"./Foo\\"), 60 | resolve: () => require.resolveWeak(\\"./Foo\\"), 61 | chunkName: () => \\"Foo\\" 62 | }); 63 | " 64 | `; 65 | 66 | exports[`dynamic import (string template + relative paths) 1`] = ` 67 | " 68 | import(\`../../base/\${page}\`) 69 | 70 | ↓ ↓ ↓ ↓ ↓ ↓ 71 | 72 | var _path2 = _interopRequireDefault(require(\\"path\\")); 73 | 74 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 75 | 76 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 77 | 78 | (0, _universalImport2.default)({ 79 | id: \\"../../base/\${page}\\", 80 | load: () => Promise.all([import( 81 | /* webpackChunkName: 'base/[request]' */ 82 | \`../../base/\${page}\`)]).then(proms => proms[0]), 83 | path: () => _path2.default.join(__dirname, \`../../base/\${page}\`), 84 | resolve: () => require.resolveWeak(\`../../base/\${page}\`), 85 | chunkName: () => \`base/\${page}\` 86 | }); 87 | " 88 | `; 89 | 90 | exports[`dynamic import (string template - dynamic at 1st segment) 1`] = ` 91 | " 92 | import(\`./\${page}\`) 93 | 94 | ↓ ↓ ↓ ↓ ↓ ↓ 95 | 96 | var _path2 = _interopRequireDefault(require(\\"path\\")); 97 | 98 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 99 | 100 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 101 | 102 | (0, _universalImport2.default)({ 103 | id: \\"./\${page}\\", 104 | load: () => Promise.all([import( 105 | /* webpackChunkName: '[request]' */ 106 | \`./\${page}\`)]).then(proms => proms[0]), 107 | path: () => _path2.default.join(__dirname, \`./\${page}\`), 108 | resolve: () => require.resolveWeak(\`./\${page}\`), 109 | chunkName: () => \`\${page}\` 110 | }); 111 | " 112 | `; 113 | 114 | exports[`dynamic import (string template with multiple nested folders) 1`] = ` 115 | " 116 | import(\`./base/\${page}/nested/{$another}folder\`) 117 | 118 | ↓ ↓ ↓ ↓ ↓ ↓ 119 | 120 | var _path2 = _interopRequireDefault(require(\\"path\\")); 121 | 122 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 123 | 124 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 125 | 126 | (0, _universalImport2.default)({ 127 | id: \\"./base/\${page}/nested/{$another}folder\\", 128 | load: () => Promise.all([import( 129 | /* webpackChunkName: 'base/[request]' */ 130 | \`./base/\${page}/nested/{$another}folder\`)]).then(proms => proms[0]), 131 | path: () => _path2.default.join(__dirname, \`./base/\${page}/nested/{$another}folder\`), 132 | resolve: () => require.resolveWeak(\`./base/\${page}/nested/{$another}folder\`), 133 | chunkName: () => \`base/\${page}/nested/{$another}folder\` 134 | }); 135 | " 136 | `; 137 | 138 | exports[`dynamic import (string template with nested folder) 1`] = ` 139 | " 140 | import(\`./base/\${page}/nested/folder\`) 141 | 142 | ↓ ↓ ↓ ↓ ↓ ↓ 143 | 144 | var _path2 = _interopRequireDefault(require(\\"path\\")); 145 | 146 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 147 | 148 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 149 | 150 | (0, _universalImport2.default)({ 151 | id: \\"./base/\${page}/nested/folder\\", 152 | load: () => Promise.all([import( 153 | /* webpackChunkName: 'base/[request]' */ 154 | \`./base/\${page}/nested/folder\`)]).then(proms => proms[0]), 155 | path: () => _path2.default.join(__dirname, \`./base/\${page}/nested/folder\`), 156 | resolve: () => require.resolveWeak(\`./base/\${page}/nested/folder\`), 157 | chunkName: () => \`base/\${page}/nested/folder\` 158 | }); 159 | " 160 | `; 161 | 162 | exports[`dynamic import (string template) 1`] = ` 163 | " 164 | import(\`./base/\${page}\`) 165 | 166 | ↓ ↓ ↓ ↓ ↓ ↓ 167 | 168 | var _path2 = _interopRequireDefault(require(\\"path\\")); 169 | 170 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 171 | 172 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 173 | 174 | (0, _universalImport2.default)({ 175 | id: \\"./base/\${page}\\", 176 | load: () => Promise.all([import( 177 | /* webpackChunkName: 'base/[request]' */ 178 | \`./base/\${page}\`)]).then(proms => proms[0]), 179 | path: () => _path2.default.join(__dirname, \`./base/\${page}\`), 180 | resolve: () => require.resolveWeak(\`./base/\${page}\`), 181 | chunkName: () => \`base/\${page}\` 182 | }); 183 | " 184 | `; 185 | 186 | exports[`existing chunkName + strips out unknown things 1`] = ` 187 | " 188 | import( 189 | /* webpackFakeProperty1: \\"Lazy\\" */ 190 | /* webpackChunkName: 'Bar'*/ 191 | /* webpackFakeProperty3123: /foobar/ */ 192 | \\"./Foo\\") 193 | 194 | ↓ ↓ ↓ ↓ ↓ ↓ 195 | 196 | var _path2 = _interopRequireDefault(require(\\"path\\")); 197 | 198 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 199 | 200 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 201 | 202 | (0, _universalImport2.default)({ 203 | id: \\"./Foo\\", 204 | load: () => Promise.all([import( 205 | /* webpackChunkName: 'Foo' */ 206 | \\"./Foo\\")]).then(proms => proms[0]), 207 | path: () => _path2.default.join(__dirname, \\"./Foo\\"), 208 | resolve: () => require.resolveWeak(\\"./Foo\\"), 209 | chunkName: () => \\"Foo\\" 210 | }); 211 | " 212 | `; 213 | 214 | exports[`existing chunkName + webpackPrefetch 1`] = ` 215 | " 216 | import( 217 | /* webpackChunkName: 'Bar'*/ 218 | /* webpackPrefetch: true */ 219 | \\"./Foo\\") 220 | 221 | ↓ ↓ ↓ ↓ ↓ ↓ 222 | 223 | var _path2 = _interopRequireDefault(require(\\"path\\")); 224 | 225 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 226 | 227 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 228 | 229 | (0, _universalImport2.default)({ 230 | id: \\"./Foo\\", 231 | load: () => Promise.all([import( 232 | /* webpackPrefetch: true */ 233 | 234 | /* webpackChunkName: 'Bar' */ 235 | \\"./Foo\\")]).then(proms => proms[0]), 236 | path: () => _path2.default.join(__dirname, \\"./Foo\\"), 237 | resolve: () => require.resolveWeak(\\"./Foo\\"), 238 | chunkName: () => \\"Bar\\" 239 | }); 240 | " 241 | `; 242 | 243 | exports[`existing chunkName + webpackPreload 1`] = ` 244 | " 245 | import( 246 | /* webpackChunkName: 'Bar'*/ 247 | /* webpackPreload: true */ 248 | \\"./Foo\\") 249 | 250 | ↓ ↓ ↓ ↓ ↓ ↓ 251 | 252 | var _path2 = _interopRequireDefault(require(\\"path\\")); 253 | 254 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 255 | 256 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 257 | 258 | (0, _universalImport2.default)({ 259 | id: \\"./Foo\\", 260 | load: () => Promise.all([import( 261 | /* webpackPreload: true */ 262 | 263 | /* webpackChunkName: 'Bar' */ 264 | \\"./Foo\\")]).then(proms => proms[0]), 265 | path: () => _path2.default.join(__dirname, \\"./Foo\\"), 266 | resolve: () => require.resolveWeak(\\"./Foo\\"), 267 | chunkName: () => \\"Bar\\" 268 | }); 269 | " 270 | `; 271 | 272 | exports[`existing chunkName + webpackmode + webpackInclude + webpackExclude + webpackIgnore 1`] = ` 273 | " 274 | import( 275 | /* webpackChunkName: 'Bar'*/ 276 | /* webpackMode: \\"Lazy\\" */ 277 | /* webpackInclude: /*.js$/ */ 278 | /* webpackExclude: /(?!*test.js)$/ */ 279 | /* webpackIgnore: true */ 280 | \\"./Foo\\") 281 | 282 | ↓ ↓ ↓ ↓ ↓ ↓ 283 | 284 | var _path2 = _interopRequireDefault(require(\\"path\\")); 285 | 286 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 287 | 288 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 289 | 290 | (0, _universalImport2.default)({ 291 | id: \\"./Foo\\", 292 | load: () => Promise.all([import( 293 | /* webpackIgnore: true */ 294 | 295 | /* webpackExclude: /(?!*test.js)$/ */ 296 | 297 | /* webpackInclude: /*.js$/ */ 298 | 299 | /* webpackMode: \\"Lazy\\" */ 300 | 301 | /* webpackChunkName: 'Bar' */ 302 | \\"./Foo\\")]).then(proms => proms[0]), 303 | path: () => _path2.default.join(__dirname, \\"./Foo\\"), 304 | resolve: () => require.resolveWeak(\\"./Foo\\"), 305 | chunkName: () => \\"Bar\\" 306 | }); 307 | " 308 | `; 309 | 310 | exports[`existing chunkName + webpackmode + webpackInclude + webpackExclude 1`] = ` 311 | " 312 | import( 313 | /* webpackChunkName: 'Bar'*/ 314 | /* webpackMode: \\"Lazy\\" */ 315 | /* webpackInclude: /*.js$/ */ 316 | /* webpackExclude: /(?!*test.js)$/ */ 317 | \\"./Foo\\") 318 | 319 | ↓ ↓ ↓ ↓ ↓ ↓ 320 | 321 | var _path2 = _interopRequireDefault(require(\\"path\\")); 322 | 323 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 324 | 325 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 326 | 327 | (0, _universalImport2.default)({ 328 | id: \\"./Foo\\", 329 | load: () => Promise.all([import( 330 | /* webpackExclude: /(?!*test.js)$/ */ 331 | 332 | /* webpackInclude: /*.js$/ */ 333 | 334 | /* webpackMode: \\"Lazy\\" */ 335 | 336 | /* webpackChunkName: 'Bar' */ 337 | \\"./Foo\\")]).then(proms => proms[0]), 338 | path: () => _path2.default.join(__dirname, \\"./Foo\\"), 339 | resolve: () => require.resolveWeak(\\"./Foo\\"), 340 | chunkName: () => \\"Bar\\" 341 | }); 342 | " 343 | `; 344 | 345 | exports[`existing chunkName + webpackmode + webpackInclude 1`] = ` 346 | " 347 | import( 348 | /* webpackChunkName: 'Bar'*/ 349 | /* webpackMode: \\"Lazy\\" */ 350 | /* webpackInclude: /*.js$/ */ 351 | \\"./Foo\\") 352 | 353 | ↓ ↓ ↓ ↓ ↓ ↓ 354 | 355 | var _path2 = _interopRequireDefault(require(\\"path\\")); 356 | 357 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 358 | 359 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 360 | 361 | (0, _universalImport2.default)({ 362 | id: \\"./Foo\\", 363 | load: () => Promise.all([import( 364 | /* webpackInclude: /*.js$/ */ 365 | 366 | /* webpackMode: \\"Lazy\\" */ 367 | 368 | /* webpackChunkName: 'Bar' */ 369 | \\"./Foo\\")]).then(proms => proms[0]), 370 | path: () => _path2.default.join(__dirname, \\"./Foo\\"), 371 | resolve: () => require.resolveWeak(\\"./Foo\\"), 372 | chunkName: () => \\"Bar\\" 373 | }); 374 | " 375 | `; 376 | 377 | exports[`existing chunkName + webpackmode 1`] = ` 378 | " 379 | import(/* webpackChunkName: 'Bar'*//* webpackMode: \\"Lazy\\" */\\"./Foo\\") 380 | 381 | ↓ ↓ ↓ ↓ ↓ ↓ 382 | 383 | var _path2 = _interopRequireDefault(require(\\"path\\")); 384 | 385 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 386 | 387 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 388 | 389 | (0, _universalImport2.default)({ 390 | id: \\"./Foo\\", 391 | load: () => Promise.all([import( 392 | /* webpackMode: \\"Lazy\\" */ 393 | 394 | /* webpackChunkName: 'Bar' */ 395 | \\"./Foo\\")]).then(proms => proms[0]), 396 | path: () => _path2.default.join(__dirname, \\"./Foo\\"), 397 | resolve: () => require.resolveWeak(\\"./Foo\\"), 398 | chunkName: () => \\"Bar\\" 399 | }); 400 | " 401 | `; 402 | 403 | exports[`existing chunkName 1`] = ` 404 | " 405 | import(/* webpackChunkName: 'Bar' */\\"./Foo\\") 406 | 407 | ↓ ↓ ↓ ↓ ↓ ↓ 408 | 409 | var _path2 = _interopRequireDefault(require(\\"path\\")); 410 | 411 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 412 | 413 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 414 | 415 | (0, _universalImport2.default)({ 416 | id: \\"./Foo\\", 417 | load: () => Promise.all([import( 418 | /* webpackChunkName: 'Bar' */ 419 | \\"./Foo\\")]).then(proms => proms[0]), 420 | path: () => _path2.default.join(__dirname, \\"./Foo\\"), 421 | resolve: () => require.resolveWeak(\\"./Foo\\"), 422 | chunkName: () => \\"Bar\\" 423 | }); 424 | " 425 | `; 426 | 427 | exports[`multiple imports 1`] = ` 428 | " 429 | import(\\"one\\"); import(\\"two\\"); import(\\"three\\"); 430 | 431 | ↓ ↓ ↓ ↓ ↓ ↓ 432 | 433 | var _path4 = _interopRequireDefault(require(\\"path\\")); 434 | 435 | var _universalImport4 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 436 | 437 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 438 | 439 | (0, _universalImport4.default)({ 440 | id: \\"one\\", 441 | load: () => Promise.all([import( 442 | /* webpackChunkName: 'one' */ 443 | \\"one\\")]).then(proms => proms[0]), 444 | path: () => _path4.default.join(__dirname, \\"one\\"), 445 | resolve: () => require.resolveWeak(\\"one\\"), 446 | chunkName: () => \\"one\\" 447 | }); 448 | (0, _universalImport4.default)({ 449 | id: \\"two\\", 450 | load: () => Promise.all([import( 451 | /* webpackChunkName: 'two' */ 452 | \\"two\\")]).then(proms => proms[0]), 453 | path: () => _path4.default.join(__dirname, \\"two\\"), 454 | resolve: () => require.resolveWeak(\\"two\\"), 455 | chunkName: () => \\"two\\" 456 | }); 457 | (0, _universalImport4.default)({ 458 | id: \\"three\\", 459 | load: () => Promise.all([import( 460 | /* webpackChunkName: 'three' */ 461 | \\"three\\")]).then(proms => proms[0]), 462 | path: () => _path4.default.join(__dirname, \\"three\\"), 463 | resolve: () => require.resolveWeak(\\"three\\"), 464 | chunkName: () => \\"three\\" 465 | }); 466 | " 467 | `; 468 | 469 | exports[`no chunkName + webpackPrefetch 1`] = ` 470 | " 471 | import( 472 | /* webpackPrefetch: true */ 473 | \\"./Foo\\") 474 | 475 | ↓ ↓ ↓ ↓ ↓ ↓ 476 | 477 | var _path2 = _interopRequireDefault(require(\\"path\\")); 478 | 479 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 480 | 481 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 482 | 483 | (0, _universalImport2.default)({ 484 | id: \\"./Foo\\", 485 | load: () => Promise.all([import( 486 | /* webpackPrefetch: true */ 487 | 488 | /* webpackChunkName: 'Foo' */ 489 | \\"./Foo\\")]).then(proms => proms[0]), 490 | path: () => _path2.default.join(__dirname, \\"./Foo\\"), 491 | resolve: () => require.resolveWeak(\\"./Foo\\"), 492 | chunkName: () => \\"Foo\\" 493 | }); 494 | " 495 | `; 496 | 497 | exports[`no chunkName + webpackPreload 1`] = ` 498 | " 499 | import( 500 | /* webpackPreload: true */ 501 | \\"./Foo\\") 502 | 503 | ↓ ↓ ↓ ↓ ↓ ↓ 504 | 505 | var _path2 = _interopRequireDefault(require(\\"path\\")); 506 | 507 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 508 | 509 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 510 | 511 | (0, _universalImport2.default)({ 512 | id: \\"./Foo\\", 513 | load: () => Promise.all([import( 514 | /* webpackPreload: true */ 515 | 516 | /* webpackChunkName: 'Foo' */ 517 | \\"./Foo\\")]).then(proms => proms[0]), 518 | path: () => _path2.default.join(__dirname, \\"./Foo\\"), 519 | resolve: () => require.resolveWeak(\\"./Foo\\"), 520 | chunkName: () => \\"Foo\\" 521 | }); 522 | " 523 | `; 524 | 525 | exports[`no chunkName + webpackmode + webpackInclude + webpackExclude + webpackIgnore 1`] = ` 526 | " 527 | import( 528 | /* webpackMode: \\"Lazy\\" */ 529 | /* webpackInclude: /*.js$/ */ 530 | /* webpackExclude: /(?!*test.js)$/ */ 531 | /* webpackIgnore: true */ 532 | \\"./Foo\\") 533 | 534 | ↓ ↓ ↓ ↓ ↓ ↓ 535 | 536 | var _path2 = _interopRequireDefault(require(\\"path\\")); 537 | 538 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 539 | 540 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 541 | 542 | (0, _universalImport2.default)({ 543 | id: \\"./Foo\\", 544 | load: () => Promise.all([import( 545 | /* webpackIgnore: true */ 546 | 547 | /* webpackExclude: /(?!*test.js)$/ */ 548 | 549 | /* webpackInclude: /*.js$/ */ 550 | 551 | /* webpackMode: \\"Lazy\\" */ 552 | 553 | /* webpackChunkName: 'Foo' */ 554 | \\"./Foo\\")]).then(proms => proms[0]), 555 | path: () => _path2.default.join(__dirname, \\"./Foo\\"), 556 | resolve: () => require.resolveWeak(\\"./Foo\\"), 557 | chunkName: () => \\"Foo\\" 558 | }); 559 | " 560 | `; 561 | 562 | exports[`no chunkName + webpackmode + webpackInclude + webpackExclude 1`] = ` 563 | " 564 | import( 565 | /* webpackMode: \\"Lazy\\" */ 566 | /* webpackInclude: /*.js$/ */ 567 | /* webpackExclude: /(?!*test.js)$/ */ 568 | \\"./Foo\\") 569 | 570 | ↓ ↓ ↓ ↓ ↓ ↓ 571 | 572 | var _path2 = _interopRequireDefault(require(\\"path\\")); 573 | 574 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 575 | 576 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 577 | 578 | (0, _universalImport2.default)({ 579 | id: \\"./Foo\\", 580 | load: () => Promise.all([import( 581 | /* webpackExclude: /(?!*test.js)$/ */ 582 | 583 | /* webpackInclude: /*.js$/ */ 584 | 585 | /* webpackMode: \\"Lazy\\" */ 586 | 587 | /* webpackChunkName: 'Foo' */ 588 | \\"./Foo\\")]).then(proms => proms[0]), 589 | path: () => _path2.default.join(__dirname, \\"./Foo\\"), 590 | resolve: () => require.resolveWeak(\\"./Foo\\"), 591 | chunkName: () => \\"Foo\\" 592 | }); 593 | " 594 | `; 595 | 596 | exports[`no chunkName + webpackmode + webpackInclude 1`] = ` 597 | " 598 | import( 599 | /* webpackMode: \\"Lazy\\" */ 600 | /* webpackInclude: /*.js$/ */ 601 | \\"./Foo\\") 602 | 603 | ↓ ↓ ↓ ↓ ↓ ↓ 604 | 605 | var _path2 = _interopRequireDefault(require(\\"path\\")); 606 | 607 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 608 | 609 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 610 | 611 | (0, _universalImport2.default)({ 612 | id: \\"./Foo\\", 613 | load: () => Promise.all([import( 614 | /* webpackInclude: /*.js$/ */ 615 | 616 | /* webpackMode: \\"Lazy\\" */ 617 | 618 | /* webpackChunkName: 'Foo' */ 619 | \\"./Foo\\")]).then(proms => proms[0]), 620 | path: () => _path2.default.join(__dirname, \\"./Foo\\"), 621 | resolve: () => require.resolveWeak(\\"./Foo\\"), 622 | chunkName: () => \\"Foo\\" 623 | }); 624 | " 625 | `; 626 | 627 | exports[`no chunkName + webpackmode 1`] = ` 628 | " 629 | import( 630 | /* webpackMode: \\"Lazy\\" */ 631 | \\"./Foo\\") 632 | 633 | ↓ ↓ ↓ ↓ ↓ ↓ 634 | 635 | var _path2 = _interopRequireDefault(require(\\"path\\")); 636 | 637 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 638 | 639 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 640 | 641 | (0, _universalImport2.default)({ 642 | id: \\"./Foo\\", 643 | load: () => Promise.all([import( 644 | /* webpackMode: \\"Lazy\\" */ 645 | 646 | /* webpackChunkName: 'Foo' */ 647 | \\"./Foo\\")]).then(proms => proms[0]), 648 | path: () => _path2.default.join(__dirname, \\"./Foo\\"), 649 | resolve: () => require.resolveWeak(\\"./Foo\\"), 650 | chunkName: () => \\"Foo\\" 651 | }); 652 | " 653 | `; 654 | 655 | exports[`static import (import as function with relative paths + nested folder) 1`] = ` 656 | " 657 | const obj = {component:()=>import(\`../components/nestedComponent\`)}; ()=> obj.component() 658 | 659 | ↓ ↓ ↓ ↓ ↓ ↓ 660 | 661 | var _path2 = _interopRequireDefault(require(\\"path\\")); 662 | 663 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 664 | 665 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 666 | 667 | const obj = { 668 | component: () => (0, _universalImport2.default)({ 669 | id: \\"../components/nestedComponent\\", 670 | load: () => Promise.all([import( 671 | /* webpackChunkName: 'components/nestedComponent' */ 672 | \`../components/nestedComponent\`)]).then(proms => proms[0]), 673 | path: () => _path2.default.join(__dirname, \`../components/nestedComponent\`), 674 | resolve: () => require.resolveWeak(\`../components/nestedComponent\`), 675 | chunkName: () => \`components/nestedComponent\` 676 | }) 677 | }; 678 | 679 | () => obj.component(); 680 | " 681 | `; 682 | 683 | exports[`static import (relative paths + nested folder) 1`] = ` 684 | " 685 | import(\`../components/nestedComponent\`) 686 | 687 | ↓ ↓ ↓ ↓ ↓ ↓ 688 | 689 | var _path2 = _interopRequireDefault(require(\\"path\\")); 690 | 691 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 692 | 693 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 694 | 695 | (0, _universalImport2.default)({ 696 | id: \\"../components/nestedComponent\\", 697 | load: () => Promise.all([import( 698 | /* webpackChunkName: 'components/nestedComponent' */ 699 | \`../components/nestedComponent\`)]).then(proms => proms[0]), 700 | path: () => _path2.default.join(__dirname, \`../components/nestedComponent\`), 701 | resolve: () => require.resolveWeak(\`../components/nestedComponent\`), 702 | chunkName: () => \`components/nestedComponent\` 703 | }); 704 | " 705 | `; 706 | 707 | exports[`static import (string template + relative paths) 1`] = ` 708 | " 709 | import(\`../../base\`) 710 | 711 | ↓ ↓ ↓ ↓ ↓ ↓ 712 | 713 | var _path2 = _interopRequireDefault(require(\\"path\\")); 714 | 715 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 716 | 717 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 718 | 719 | (0, _universalImport2.default)({ 720 | id: \\"../../base\\", 721 | load: () => Promise.all([import( 722 | /* webpackChunkName: 'base' */ 723 | \`../../base\`)]).then(proms => proms[0]), 724 | path: () => _path2.default.join(__dirname, \`../../base\`), 725 | resolve: () => require.resolveWeak(\`../../base\`), 726 | chunkName: () => \`base\` 727 | }); 728 | " 729 | `; 730 | 731 | exports[`static import (string template) 1`] = ` 732 | " 733 | import(\`./base\`) 734 | 735 | ↓ ↓ ↓ ↓ ↓ ↓ 736 | 737 | var _path2 = _interopRequireDefault(require(\\"path\\")); 738 | 739 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 740 | 741 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 742 | 743 | (0, _universalImport2.default)({ 744 | id: \\"./base\\", 745 | load: () => Promise.all([import( 746 | /* webpackChunkName: 'base' */ 747 | \`./base\`)]).then(proms => proms[0]), 748 | path: () => _path2.default.join(__dirname, \`./base\`), 749 | resolve: () => require.resolveWeak(\`./base\`), 750 | chunkName: () => \`base\` 751 | }); 752 | " 753 | `; 754 | 755 | exports[`static import (with file extension) 1`] = ` 756 | " 757 | import(\\"./Foo.js\\") 758 | 759 | ↓ ↓ ↓ ↓ ↓ ↓ 760 | 761 | var _path2 = _interopRequireDefault(require(\\"path\\")); 762 | 763 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 764 | 765 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 766 | 767 | (0, _universalImport2.default)({ 768 | id: \\"./Foo.js\\", 769 | load: () => Promise.all([import( 770 | /* webpackChunkName: 'Foo' */ 771 | \\"./Foo.js\\")]).then(proms => proms[0]), 772 | path: () => _path2.default.join(__dirname, \\"./Foo.js\\"), 773 | resolve: () => require.resolveWeak(\\"./Foo.js\\"), 774 | chunkName: () => \\"Foo\\" 775 | }); 776 | " 777 | `; 778 | 779 | exports[`static import (with relative paths) 1`] = ` 780 | " 781 | import(\\"../../Foo\\") 782 | 783 | ↓ ↓ ↓ ↓ ↓ ↓ 784 | 785 | var _path2 = _interopRequireDefault(require(\\"path\\")); 786 | 787 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 788 | 789 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 790 | 791 | (0, _universalImport2.default)({ 792 | id: \\"../../Foo\\", 793 | load: () => Promise.all([import( 794 | /* webpackChunkName: 'Foo' */ 795 | \\"../../Foo\\")]).then(proms => proms[0]), 796 | path: () => _path2.default.join(__dirname, \\"../../Foo\\"), 797 | resolve: () => require.resolveWeak(\\"../../Foo\\"), 798 | chunkName: () => \\"Foo\\" 799 | }); 800 | " 801 | `; 802 | 803 | exports[`static import 1`] = ` 804 | " 805 | import(\\"./Foo\\") 806 | 807 | ↓ ↓ ↓ ↓ ↓ ↓ 808 | 809 | var _path2 = _interopRequireDefault(require(\\"path\\")); 810 | 811 | var _universalImport2 = _interopRequireDefault(require(\\"babel-plugin-universal-import/universalImport\\")); 812 | 813 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 814 | 815 | (0, _universalImport2.default)({ 816 | id: \\"./Foo\\", 817 | load: () => Promise.all([import( 818 | /* webpackChunkName: 'Foo' */ 819 | \\"./Foo\\")]).then(proms => proms[0]), 820 | path: () => _path2.default.join(__dirname, \\"./Foo\\"), 821 | resolve: () => require.resolveWeak(\\"./Foo\\"), 822 | chunkName: () => \\"Foo\\" 823 | }); 824 | " 825 | `; 826 | -------------------------------------------------------------------------------- /__tests__/index.test.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-template-curly-in-string */ 2 | 3 | const pluginTester = require('babel-plugin-tester') 4 | const createBabylonOptions = require('babylon-options') 5 | const plugin = require('../index') 6 | const babel = require('@babel/core') 7 | 8 | const babelOptions = { 9 | parserOpts: createBabylonOptions({ 10 | plugins: ['dynamicImport'] 11 | }), 12 | presets: ['@babel/preset-react'], 13 | plugins: [ 14 | '@babel/plugin-syntax-dynamic-import', 15 | ['@babel/plugin-transform-modules-commonjs', { strictMode: false }] 16 | ], 17 | babelrc: false 18 | } 19 | 20 | pluginTester({ 21 | plugin, 22 | babelOptions, 23 | snapshot: true, 24 | tests: { 25 | 'static import': 'import("./Foo")', 26 | 'static import (with relative paths)': 'import("../../Foo")', 27 | 'static import (with file extension)': 'import("./Foo.js")', 28 | 'static import (string template)': 'import(`./base`)', 29 | 'static import (string template + relative paths)': 'import(`../../base`)', 30 | 'static import (import as function with relative paths + nested folder)': 31 | 'const obj = {component:()=>import(`../components/nestedComponent`)}; ()=> obj.component()', 32 | 'static import (relative paths + nested folder)': 33 | 'import(`../components/nestedComponent`)', 34 | 'dynamic import (string template)': 'import(`./base/${page}`)', 35 | 'dynamic import (string template with nested folder)': 36 | 'import(`./base/${page}/nested/folder`)', 37 | 'dynamic import (string template with multiple nested folders)': 38 | 'import(`./base/${page}/nested/{$another}folder`)', 39 | 'dynamic import (string template - dynamic at 1st segment)': 40 | 'import(`./${page}`)', 41 | 'dynamic import (string template + relative paths)': 42 | 'import(`../../base/${page}`)', 43 | 'await import() should receive a thennable without calling .then': 44 | 'async ({ page }) => await import(`../components/${page}`);', 45 | 'babelServer: true': { 46 | code: 'import("./Foo")', 47 | pluginOptions: { babelServer: true } 48 | }, 49 | 'disableWarnings: true': { 50 | code: 'import("./Foo")', 51 | pluginOptions: { disableWarnings: true } 52 | }, 53 | 'existing chunkName': 'import(/* webpackChunkName: \'Bar\' */"./Foo")', 54 | 'multiple imports': 'import("one"); import("two"); import("three");', 55 | 'existing chunkName + webpackmode': `import(/* webpackChunkName: 'Bar'*//* webpackMode: "Lazy" */"./Foo")`, 56 | 'existing chunkName + webpackmode + webpackInclude': ` 57 | import( 58 | /* webpackChunkName: 'Bar'*/ 59 | /* webpackMode: "Lazy" */ 60 | /* webpackInclude: /*.js$/ */ 61 | "./Foo")`, 62 | 'existing chunkName + webpackmode + webpackInclude + webpackExclude': ` 63 | import( 64 | /* webpackChunkName: 'Bar'*/ 65 | /* webpackMode: "Lazy" */ 66 | /* webpackInclude: /*.js$/ */ 67 | /* webpackExclude: /(?!*test.js)$/ */ 68 | "./Foo")`, 69 | 'existing chunkName + webpackmode + webpackInclude + webpackExclude + webpackIgnore': ` 70 | import( 71 | /* webpackChunkName: 'Bar'*/ 72 | /* webpackMode: "Lazy" */ 73 | /* webpackInclude: /*.js$/ */ 74 | /* webpackExclude: /(?!*test.js)$/ */ 75 | /* webpackIgnore: true */ 76 | "./Foo")`, 77 | 'existing chunkName + strips out unknown things': ` 78 | import( 79 | /* webpackFakeProperty1: "Lazy" */ 80 | /* webpackChunkName: 'Bar'*/ 81 | /* webpackFakeProperty3123: /foobar/ */ 82 | "./Foo")`, 83 | 'no chunkName + webpackmode + webpackInclude + webpackExclude + webpackIgnore': ` 84 | import( 85 | /* webpackMode: "Lazy" */ 86 | /* webpackInclude: /*.js$/ */ 87 | /* webpackExclude: /(?!*test.js)$/ */ 88 | /* webpackIgnore: true */ 89 | "./Foo")`, 90 | 'no chunkName + webpackmode + webpackInclude + webpackExclude': ` 91 | import( 92 | /* webpackMode: "Lazy" */ 93 | /* webpackInclude: /*.js$/ */ 94 | /* webpackExclude: /(?!*test.js)$/ */ 95 | "./Foo")`, 96 | 'no chunkName + webpackmode + webpackInclude': ` 97 | import( 98 | /* webpackMode: "Lazy" */ 99 | /* webpackInclude: /*.js$/ */ 100 | "./Foo")`, 101 | 'no chunkName + webpackmode': ` 102 | import( 103 | /* webpackMode: "Lazy" */ 104 | "./Foo")`, 105 | 'no chunkName + webpackPreload': ` 106 | import( 107 | /* webpackPreload: true */ 108 | "./Foo")`, 109 | 'no chunkName + webpackPrefetch': ` 110 | import( 111 | /* webpackPrefetch: true */ 112 | "./Foo")`, 113 | 'existing chunkName + webpackPreload': ` 114 | import( 115 | /* webpackChunkName: 'Bar'*/ 116 | /* webpackPreload: true */ 117 | "./Foo")`, 118 | 'existing chunkName + webpackPrefetch': ` 119 | import( 120 | /* webpackChunkName: 'Bar'*/ 121 | /* webpackPrefetch: true */ 122 | "./Foo")` 123 | } 124 | }) 125 | 126 | // toggle from test.skip to test.only when working on the plugin using Wallaby 127 | test.skip('wallaby-live-coding', () => { 128 | // const input = 'async ({ page }) => await import(`../components/${page}`);' 129 | // const input = 'import("../../Foo.js")' 130 | // const input = 'universal(props => import(`./footer/${props.experiment}`));' 131 | const input = 'import(`./base/${page}/index`)' 132 | 133 | const output = babel.transform( 134 | input, 135 | Object.assign({}, babelOptions, { 136 | plugins: babelOptions.plugins.concat([plugin]) 137 | }) 138 | ) 139 | 140 | expect(output.code).toBeDefined() 141 | }) 142 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use-strict' 2 | 3 | const validMagicStrings = [ 4 | 'webpackMode', 5 | // 'webpackMagicChunkName' gets dealt with current implementation & naming/renaming strategy 6 | 'webpackInclude', 7 | 'webpackExclude', 8 | 'webpackIgnore', 9 | 'webpackPreload', 10 | 'webpackPrefetch' 11 | ] 12 | 13 | const { addDefault } = require('@babel/helper-module-imports') 14 | 15 | const path = require('path') 16 | 17 | const visited = Symbol('visited') 18 | 19 | const IMPORT_UNIVERSAL_DEFAULT = { 20 | id: Symbol('universalImportId'), 21 | source: 'babel-plugin-universal-import/universalImport', 22 | nameHint: 'universalImport' 23 | } 24 | 25 | const IMPORT_PATH_DEFAULT = { 26 | id: Symbol('pathId'), 27 | source: 'path', 28 | nameHint: 'path' 29 | } 30 | 31 | function getImportArgPath(p) { 32 | return p.parentPath.get('arguments')[0] 33 | } 34 | 35 | function trimChunkNameBaseDir(baseDir) { 36 | return baseDir.replace(/^[./]+|(\.js$)/g, '') 37 | } 38 | 39 | function getImport(p, { source, nameHint }) { 40 | return addDefault(p, source, { nameHint }) 41 | } 42 | 43 | function createTrimmedChunkName(t, importArgNode) { 44 | if (importArgNode.quasis) { 45 | let quasis = importArgNode.quasis.slice(0) 46 | const baseDir = trimChunkNameBaseDir(quasis[0].value.cooked) 47 | quasis[0] = Object.assign({}, quasis[0], { 48 | value: { raw: baseDir, cooked: baseDir } 49 | }) 50 | 51 | quasis = quasis.map((quasi, i) => (i > 0 ? prepareQuasi(quasi) : quasi)) 52 | 53 | return Object.assign({}, importArgNode, { 54 | quasis 55 | }) 56 | } 57 | 58 | const moduleName = trimChunkNameBaseDir(importArgNode.value) 59 | return t.stringLiteral(moduleName) 60 | } 61 | 62 | function prepareQuasi(quasi) { 63 | return Object.assign({}, quasi, { 64 | value: { raw: quasi.value.cooked, cooked: quasi.value.cooked } 65 | }) 66 | } 67 | 68 | function getMagicWebpackComments(importArgNode) { 69 | const { leadingComments } = importArgNode 70 | const results = [] 71 | if (leadingComments && leadingComments.length) { 72 | leadingComments.forEach(comment => { 73 | try { 74 | const validMagicString = validMagicStrings.filter(str => 75 | new RegExp(`${str}\\w*:`).test(comment.value) 76 | ) 77 | // keep this comment if we found a match 78 | if (validMagicString && validMagicString.length === 1) { 79 | results.push(comment) 80 | } 81 | } 82 | catch (e) { 83 | // eat the error, but don't give up 84 | } 85 | }) 86 | } 87 | return results 88 | } 89 | 90 | function getMagicCommentChunkName(importArgNode) { 91 | const { quasis, expressions } = importArgNode 92 | if (!quasis) return trimChunkNameBaseDir(importArgNode.value) 93 | 94 | const baseDir = quasis[0].value.cooked 95 | const hasExpressions = expressions.length > 0 96 | const chunkName = baseDir + (hasExpressions ? '[request]' : '') 97 | return trimChunkNameBaseDir(chunkName) 98 | } 99 | 100 | function getComponentId(t, importArgNode) { 101 | const { quasis, expressions } = importArgNode 102 | if (!quasis) return importArgNode.value 103 | 104 | return quasis.reduce((str, quasi, i) => { 105 | const q = quasi.value.cooked 106 | const id = expressions[i] && expressions[i].name 107 | str += id ? `${q}\${${id}}` : q 108 | return str 109 | }, '') 110 | } 111 | 112 | function existingMagicCommentChunkName(importArgNode) { 113 | const { leadingComments } = importArgNode 114 | if ( 115 | leadingComments && 116 | leadingComments.length && 117 | leadingComments[0].value.indexOf('webpackChunkName') !== -1 118 | ) { 119 | try { 120 | return leadingComments[0].value 121 | .split('webpackChunkName:')[1] 122 | .replace(/["']/g, '') 123 | .trim() 124 | } 125 | catch (e) { 126 | return null 127 | } 128 | } 129 | return null 130 | } 131 | 132 | function idOption(t, importArgNode) { 133 | const id = getComponentId(t, importArgNode) 134 | return t.objectProperty(t.identifier('id'), t.stringLiteral(id)) 135 | } 136 | 137 | function fileOption(t, p) { 138 | return t.objectProperty( 139 | t.identifier('file'), 140 | t.stringLiteral( 141 | path.relative(__dirname, p.hub.file.opts.filename || '') || '' 142 | ) 143 | ) 144 | } 145 | 146 | function loadOption(t, loadTemplate, p, importArgNode) { 147 | const argPath = getImportArgPath(p) 148 | const generatedChunkName = getMagicCommentChunkName(importArgNode) 149 | const otherValidMagicComments = getMagicWebpackComments(importArgNode) 150 | const existingChunkName = t.existingChunkName 151 | const chunkName = existingChunkName || generatedChunkName 152 | 153 | delete argPath.node.leadingComments 154 | argPath.addComment('leading', ` webpackChunkName: '${chunkName}' `) 155 | otherValidMagicComments.forEach(validLeadingComment => 156 | argPath.addComment('leading', validLeadingComment.value) 157 | ) 158 | 159 | const load = loadTemplate({ 160 | IMPORT: argPath.parent 161 | }).expression 162 | 163 | return t.objectProperty(t.identifier('load'), load) 164 | } 165 | 166 | function pathOption(t, pathTemplate, p, importArgNode) { 167 | const path = pathTemplate({ 168 | PATH: getImport(p, IMPORT_PATH_DEFAULT), 169 | MODULE: importArgNode 170 | }).expression 171 | 172 | return t.objectProperty(t.identifier('path'), path) 173 | } 174 | 175 | function resolveOption(t, resolveTemplate, importArgNode) { 176 | const resolve = resolveTemplate({ 177 | MODULE: importArgNode 178 | }).expression 179 | 180 | return t.objectProperty(t.identifier('resolve'), resolve) 181 | } 182 | 183 | function chunkNameOption(t, chunkNameTemplate, importArgNode) { 184 | const existingChunkName = t.existingChunkName 185 | const generatedChunk = createTrimmedChunkName(t, importArgNode) 186 | const trimmedChunkName = existingChunkName 187 | ? t.stringLiteral(existingChunkName) 188 | : generatedChunk 189 | 190 | const chunkName = chunkNameTemplate({ 191 | MODULE: trimmedChunkName 192 | }).expression 193 | 194 | return t.objectProperty(t.identifier('chunkName'), chunkName) 195 | } 196 | 197 | module.exports = function universalImportPlugin({ types: t, template }) { 198 | const chunkNameTemplate = template('() => MODULE') 199 | const pathTemplate = template('() => PATH.join(__dirname, MODULE)') 200 | const resolveTemplate = template('() => require.resolveWeak(MODULE)') 201 | const loadTemplate = template( 202 | '() => Promise.all([IMPORT]).then(proms => proms[0])' 203 | ) 204 | 205 | return { 206 | name: 'universal-import', 207 | visitor: { 208 | Import(p) { 209 | if (p[visited]) return 210 | p[visited] = true 211 | 212 | const importArgNode = getImportArgPath(p).node 213 | t.existingChunkName = existingMagicCommentChunkName(importArgNode) 214 | // no existing chunkname, no problem - we will reuse that for fixing nested chunk names 215 | 216 | const universalImport = getImport(p, IMPORT_UNIVERSAL_DEFAULT) 217 | 218 | // if being used in an await statement, return load() promise 219 | if ( 220 | p.parentPath.parentPath.isYieldExpression() || // await transformed already 221 | t.isAwaitExpression(p.parentPath.parentPath.node) // await not transformed already 222 | ) { 223 | const func = t.callExpression(universalImport, [ 224 | loadOption(t, loadTemplate, p, importArgNode).value, 225 | t.booleanLiteral(false) 226 | ]) 227 | 228 | p.parentPath.replaceWith(func) 229 | return 230 | } 231 | 232 | const opts = (this.opts.babelServer 233 | ? [ 234 | idOption(t, importArgNode), 235 | this.opts.includeFileName ? fileOption(t, p) : undefined, 236 | pathOption(t, pathTemplate, p, importArgNode), 237 | resolveOption(t, resolveTemplate, importArgNode), 238 | chunkNameOption(t, chunkNameTemplate, importArgNode) 239 | ] 240 | : [ 241 | idOption(t, importArgNode), 242 | this.opts.includeFileName ? fileOption(t, p) : undefined, 243 | loadOption(t, loadTemplate, p, importArgNode), // only when not on a babel-server 244 | pathOption(t, pathTemplate, p, importArgNode), 245 | resolveOption(t, resolveTemplate, importArgNode), 246 | chunkNameOption(t, chunkNameTemplate, importArgNode) 247 | ] 248 | ).filter(Boolean) 249 | 250 | const options = t.objectExpression(opts) 251 | 252 | const func = t.callExpression(universalImport, [options]) 253 | delete t.existingChunkName 254 | p.parentPath.replaceWith(func) 255 | } 256 | } 257 | } 258 | } 259 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "babel-plugin-universal-import", 3 | "version": "3.1.2", 4 | "description": "Babel plugin to transform import() into its Universal counterpart", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/faceyspacey/babel-plugin-universal-import.git" 9 | }, 10 | "bugs": { 11 | "url": "https://github.com/faceyspacey/babel-plugin-universal-import/issues" 12 | }, 13 | "homepage": "https://github.com/faceyspacey/babel-plugin-universal-import#readme", 14 | "author": "James Gillmore ", 15 | "contributors": [ 16 | "Zack Jackson (https://github.com/ScriptedAlchemy)" 17 | ], 18 | "license": "MIT", 19 | "scripts": { 20 | "test": "jest", 21 | "lint": "eslint --fix ./", 22 | "format": "prettier --single-quote --parser=flow --semi=false --write '{src,__tests__,__test-helpers__}/**/*.js' && npm run lint", 23 | "precommit": "lint-staged && npm test", 24 | "cm": "git-cz", 25 | "semantic-release": "semantic-release pre && npm publish && semantic-release post" 26 | }, 27 | "keywords": [ 28 | "babel", 29 | "universal", 30 | "react", 31 | "universal import", 32 | "redux-first-router", 33 | "ruc" 34 | ], 35 | "devDependencies": { 36 | "@babel/cli": "7.8.4", 37 | "@babel/core": "7.9.0", 38 | "@babel/plugin-syntax-dynamic-import": "7.8.3", 39 | "@babel/plugin-transform-modules-commonjs": "7.9.0", 40 | "@babel/preset-react": "7.9.4", 41 | "babel-core": "7.0.0-bridge.0", 42 | "babel-eslint": "10.1.0", 43 | "babel-jest": "21.2.0", 44 | "babel-plugin-tester": "5.5.2", 45 | "babylon-options": "2.0.1", 46 | "commitizen": "4.0.4", 47 | "cz-conventional-changelog": "3.1.0", 48 | "eslint": "6.8.0", 49 | "eslint-config-airbnb": "18.1.0", 50 | "eslint-plugin-flowtype": "4.6.0", 51 | "eslint-plugin-import": "2.20.2", 52 | "eslint-plugin-jsx-a11y": "6.2.3", 53 | "eslint-plugin-react": "7.19.0", 54 | "husky": "0.14.3", 55 | "jest": "21.2.1", 56 | "lint-staged": "5.0.0", 57 | "prettier": "1.19.1", 58 | "rimraf": "2.7.1", 59 | "semantic-release": "6.3.6", 60 | "travis-github-status": "1.6.3" 61 | }, 62 | "peerDependencies": { 63 | "webpack": "^4.4.0" 64 | }, 65 | "jest": { 66 | "testMatch": [ 67 | "**/?(*.)(spec|test).js?(x)" 68 | ] 69 | }, 70 | "config": { 71 | "commitizen": { 72 | "path": "./node_modules/cz-conventional-changelog" 73 | } 74 | }, 75 | "lint-staged": { 76 | "linters": { 77 | "*.js": [ 78 | "prettier --single-quote --parser=flow --semi=false --write", 79 | "eslint --fix", 80 | "git add" 81 | ] 82 | }, 83 | "verbose": true 84 | }, 85 | "dependencies": { 86 | "@babel/helper-module-imports": "^7.0.0" 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | ":combinePatchMinorReleases", 5 | ":ignoreUnstable", 6 | ":prImmediately", 7 | ":semanticPrefixFixDepsChoreOthers", 8 | ":updateNotScheduled", 9 | ":automergeDisabled", 10 | ":ignoreModulesAndTests", 11 | ":maintainLockFilesDisabled", 12 | ":autodetectPinVersions", 13 | ":prHourlyLimit4", 14 | ":prConcurrentLimit20", 15 | "group:monorepos", 16 | "group:recommended", 17 | "helpers:disableTypesNodeMajor", 18 | ":pinAllExceptPeerDependencies", 19 | ":pinOnlyDevDependencies" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/faceyspacey/babel-plugin-universal-import/1aeb6387913b1dcfee885ae4ab94116e3b7e5147/screenshot.png -------------------------------------------------------------------------------- /universal-graphic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/faceyspacey/babel-plugin-universal-import/1aeb6387913b1dcfee885ae4ab94116e3b7e5147/universal-graphic.png -------------------------------------------------------------------------------- /universalImport.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | module.exports = function(config, makeThennable) { 4 | if (makeThennable === false) return config 5 | 6 | var load = config.load 7 | config.then = function(cb) { 8 | return load().then(function(res) { 9 | return cb && cb(res) 10 | }) 11 | } 12 | config.catch = function(cb) { 13 | return load().catch(function(e) { 14 | return cb && cb(e) 15 | }) 16 | } 17 | return config 18 | } 19 | 20 | var isSet = false 21 | 22 | function setHasPlugin() { 23 | if (isSet) return 24 | var universal 25 | var isWebpack = typeof __webpack_require__ !== 'undefined' 26 | 27 | try { 28 | if (isWebpack) { 29 | var weakId = require.resolveWeak('react-universal-component') 30 | universal = __webpack_require__(weakId) 31 | } else { 32 | var nodeRequire = typeof __non_webpack_require__ === 'undefined' ? module.require : __non_webpack_require__ 33 | universal = nodeRequire('react-universal-component') 34 | } 35 | 36 | if (universal) { 37 | universal.setHasBabelPlugin() 38 | isSet = true 39 | } 40 | } catch (e) {} 41 | } 42 | 43 | setHasPlugin() 44 | -------------------------------------------------------------------------------- /wallaby.js: -------------------------------------------------------------------------------- 1 | module.exports = wallaby => { 2 | process.env.NODE_ENV = 'test' 3 | 4 | return { 5 | files: [ 6 | { pattern: 'index.js', load: false }, 7 | { pattern: 'package.json', load: false }, 8 | { pattern: '__tests__/**/*.snap', load: false } 9 | ], 10 | tests: ['__tests__/**/*.js'], 11 | 12 | env: { 13 | type: 'node', 14 | runner: 'node' 15 | }, 16 | 17 | testFramework: 'jest', 18 | compilers: { 19 | '**/*.js': wallaby.compilers.babel({ babelrc: true }) 20 | }, 21 | setup(wallaby) { 22 | // eslint-disable-next-line global-require 23 | const conf = require('./package.json').jest 24 | wallaby.testFramework.configure(conf) 25 | } 26 | } 27 | } 28 | --------------------------------------------------------------------------------