# vite-plugin-dynamic-import Enhance Vite builtin dynamic import [![NPM version](https://img.shields.io/npm/v/vite-plugin-dynamic-import.svg)](https://npmjs.org/package/vite-plugin-dynamic-import) [![NPM Downloads](https://img.shields.io/npm/dm/vite-plugin-dynamic-import.svg)](https://npmjs.org/package/vite-plugin-dynamic-import) [![awesome-vite](https://awesome.re/badge.svg)](https://github.com/vitejs/awesome-vite) English | [简体中文](https://github.com/vite-plugin/vite-plugin-dynamic-import/blob/main/README.zh-CN.md) ✅ Alias ✅ Bare module(node_modules) ✅ Compatible `@rollup/plugin-dynamic-import-vars` [limitations](https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations) ✅ Webpack-like behavior ## Install ```bash npm i vite-plugin-dynamic-import -D ``` ## Usage ```javascript import dynamicImport from 'vite-plugin-dynamic-import' export default { plugins: [ dynamicImport(/* options */) ] } ``` cases 👉 [vite-plugin-dynamic-import/test](https://github.com/vite-plugin/vite-plugin-dynamic-import/blob/main/test) #### node_modules ```js dynamicImport({ filter(id) { // `node_modules` is exclude by default, so we need to include it explicitly // https://github.com/vite-plugin/vite-plugin-dynamic-import/blob/v1.3.0/src/index.ts#L133-L135 if (id.includes('/node_modules/foo')) { return true } } }) ``` ## API dynamicImport([options]) ```ts export interface Options { filter?: (id: string) => boolean | void /** * ``` * 1. `true` - Match all possibilities as much as possible, more like `webpack` * see https://webpack.js.org/guides/dependency-management/#require-with-expression * * 2. `false` - It behaves more like `@rollup/plugin-dynamic-import-vars` * see https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#how-it-works * ``` * * @defaultValue true */ loose?: boolean /** * If you want to exclude some files * e.g `type.d.ts`, `interface.ts` */ onFiles?: (files: string[], id: string) => typeof files | void /** * Custom importee * * e.g. - append `\/*@vite-ignore*\/` in front of importee to bypass to Vite */ onResolve?: (rawImportee: string, id: string) => typeof rawImportee | void } ``` ## How and why? *We assume that the project structure is as follows* ```tree ├─┬ src │ ├─┬ views │ │ ├─┬ foo │ │ │ └── index.js │ │ └── bar.js │ └── router.js └── vite.config.js ``` ```js // vite.config.js export default { resolve: { alias: { // "@" -> "/User/project-root/src/views" '@': path.join(__dirname, 'src/views'), }, }, } ``` *Dynamic import is not well supported in Vite, such as* - Alias are not supported ```js // router.js ❌ import(`@/views/${variable}.js`) ``` - Must be relative ```js // router.js ❌ import(`/User/project-root/src/views/${variable}.js`) ``` - Must have extension ```js // router.js ❌ import(`./views/${variable}`) ``` *We try to fix these problems* For the alias in `import()`, we can calculate the relative path according to `importer` ```js // router.js ✅ import(`./views/${variable}.js`) ``` If the import path has no suffix, we use **[glob](https://www.npmjs.com/package/fast-glob)** to find the file according to `UserConfig.resolve.extensions` and supplement the suffix of the import path. So we need to list all the possibilities 1. transpire dynamic import variable, you can see [@rollup/plugin-dynamic-import-vars](https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#how-it-works) `./views/${variable}` -> `./views/*` 2. generate runtime code ```diff - // import(`./views/${variable}`) + __variableDynamicImportRuntime(`./views/${variable}`) + function __variableDynamicImportRuntime(path) { + switch (path) { + case 'foo': + case 'foo/index': + case 'foo/index.js': + return import('./views/foo/index.js'); + + case 'bar': + case 'bar.js': + return import('./views/bar.js'); + } ```