or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

0

# @rollup/plugin-dynamic-import-vars

1

2

A Rollup plugin that transforms dynamic imports containing variables into static imports with runtime switching logic. It analyzes template literals and string concatenation patterns in dynamic imports and generates glob patterns to include matching files in the bundle.

3

4

## Package Information

5

6

- **Package Name**: @rollup/plugin-dynamic-import-vars

7

- **Package Type**: npm

8

- **Language**: TypeScript

9

- **Node.js Requirements**: >= 14.0.0

10

- **Rollup Requirements**: >= 1.20.0 || 2.0.0+ || 3.0.0+ || 4.0.0+

11

- **Installation**: `npm install @rollup/plugin-dynamic-import-vars --save-dev`

12

13

## Core Imports

14

15

```javascript

16

import dynamicImportVars from '@rollup/plugin-dynamic-import-vars';

17

```

18

19

For CommonJS:

20

21

```javascript

22

const dynamicImportVars = require('@rollup/plugin-dynamic-import-vars');

23

```

24

25

Named imports:

26

27

```javascript

28

import dynamicImportVars, { dynamicImportToGlob, VariableDynamicImportError } from '@rollup/plugin-dynamic-import-vars';

29

```

30

31

## Basic Usage

32

33

```javascript

34

// rollup.config.js

35

import dynamicImportVars from '@rollup/plugin-dynamic-import-vars';

36

37

export default {

38

input: 'src/index.js',

39

output: {

40

dir: 'dist',

41

format: 'es'

42

},

43

plugins: [

44

dynamicImportVars({

45

include: ['src/**/*.js'],

46

exclude: ['node_modules/**'],

47

warnOnError: false,

48

errorWhenNoFilesFound: false

49

})

50

]

51

};

52

```

53

54

The plugin transforms code like this:

55

56

```javascript

57

// Before transformation

58

function importLocale(locale) {

59

return import(`./locales/${locale}.js`);

60

}

61

```

62

63

Into this:

64

65

```javascript

66

// After transformation

67

function __variableDynamicImportRuntime0__(path) {

68

switch (path) {

69

case './locales/en-GB.js': return import('./locales/en-GB.js');

70

case './locales/en-US.js': return import('./locales/en-US.js');

71

case './locales/nl-NL.js': return import('./locales/nl-NL.js');

72

default: return new Promise(function(resolve, reject) {

73

(typeof queueMicrotask === 'function' ? queueMicrotask : setTimeout)(

74

reject.bind(null, new Error("Unknown variable dynamic import: " + path))

75

);

76

});

77

}

78

}

79

80

function importLocale(locale) {

81

return __variableDynamicImportRuntime0__(`./locales/${locale}.js`);

82

}

83

```

84

85

## Architecture

86

87

The plugin uses a sophisticated multi-stage approach to transform dynamic imports containing variables:

88

89

- **AST Walking**: Uses `estree-walker` to traverse the parsed JavaScript AST and locate `ImportExpression` nodes

90

- **Pattern Analysis**: The `dynamicImportToGlob` utility converts variable dynamic import expressions into glob patterns by analyzing template literals, string concatenation, and method chaining patterns

91

- **File Discovery**: Uses `fast-glob` to find all files matching the generated glob pattern relative to the importing module

92

- **Runtime Function Injection**: Generates a switch-case runtime function that maps each discovered file path to a static import statement

93

- **Code Transformation**: Uses `magic-string` to replace the original dynamic import with a call to the generated runtime function while preserving import assertions

94

95

This approach ensures that all potential imports are statically analyzable and included in the bundle while maintaining runtime behavior that matches the original dynamic import logic.

96

97

## Capabilities

98

99

### Plugin Factory Function

100

101

Creates a Rollup plugin instance that transforms dynamic imports containing variables.

102

103

```javascript { .api }

104

/**

105

* Creates a Rollup plugin that transforms dynamic imports containing variables

106

* @param options - Configuration options for the plugin

107

* @returns Rollup plugin instance

108

*/

109

function dynamicImportVars(options?: RollupDynamicImportVariablesOptions): Plugin;

110

111

interface RollupDynamicImportVariablesOptions {

112

/** Files to include in transformation (picomatch pattern or array) */

113

include?: FilterPattern;

114

/** Files to exclude from transformation (picomatch pattern or array) */

115

exclude?: FilterPattern;

116

/** Whether to throw errors when no files match glob patterns (default: false) */

117

errorWhenNoFilesFound?: boolean;

118

/** Whether to warn instead of error on invalid patterns (default: false) */

119

warnOnError?: boolean;

120

}

121

122

type FilterPattern = string | RegExp | Array<string | RegExp> | null;

123

124

interface Plugin {

125

name: string;

126

transform(code: string, id: string): TransformResult | null;

127

}

128

129

interface TransformResult {

130

code: string;

131

map: SourceMap;

132

}

133

```

134

135

**Usage Examples:**

136

137

```javascript

138

// Basic usage with default options

139

export default {

140

plugins: [dynamicImportVars()]

141

};

142

143

// With specific file patterns

144

export default {

145

plugins: [

146

dynamicImportVars({

147

include: ['src/**/*.js', 'lib/**/*.mjs'],

148

exclude: ['src/legacy/**']

149

})

150

]

151

};

152

153

// With error handling configuration

154

export default {

155

plugins: [

156

dynamicImportVars({

157

warnOnError: true,

158

errorWhenNoFilesFound: true

159

})

160

]

161

};

162

```

163

164

### Dynamic Import to Glob Conversion

165

166

Utility function that converts dynamic import AST nodes to glob patterns for file matching.

167

168

```javascript { .api }

169

/**

170

* Converts a dynamic import AST node to a glob pattern

171

* @param node - AST node representing the import expression source

172

* @param sourceString - String representation of the import expression

173

* @returns Glob pattern string or null if not a variable dynamic import

174

* @throws VariableDynamicImportError for invalid import patterns

175

*/

176

function dynamicImportToGlob(node: BaseNode, sourceString: string): string | null;

177

178

interface BaseNode {

179

type: string;

180

start?: number;

181

end?: number;

182

[key: string]: any;

183

}

184

```

185

186

**Usage Examples:**

187

188

```javascript

189

import { dynamicImportToGlob } from '@rollup/plugin-dynamic-import-vars';

190

191

// Example usage in custom AST processing

192

const glob = dynamicImportToGlob(node, "`./locales/${locale}.js`");

193

// Returns: './locales/*.js'

194

195

// Handles various patterns:

196

// `./locales/${locale}.js` -> './locales/*.js'

197

// `./${folder}/${name}.js` -> './*/*.js'

198

// `./modules-${name}/index.js` -> './modules-*/index.js'

199

// './locales/' + locale + '.js' -> './locales/*.js'

200

// './locales/'.concat(locale, '.js') -> './locales/*.js'

201

```

202

203

### Variable Dynamic Import Error

204

205

Custom error class for invalid dynamic import patterns that cannot be statically analyzed.

206

207

```javascript { .api }

208

/**

209

* Error thrown when dynamic imports cannot be statically analyzed

210

* @extends Error

211

*/

212

class VariableDynamicImportError extends Error {

213

constructor(message: string);

214

}

215

```

216

217

**Common error scenarios:**

218

219

```javascript

220

// These patterns throw VariableDynamicImportError:

221

222

// Must start with ./ or ../

223

import(bar); // Invalid: bare import

224

import(`${bar}.js`); // Invalid: starts with variable

225

import(`/foo/${bar}.js`); // Invalid: absolute path

226

227

// Must end with file extension

228

import(`./foo/${bar}`); // Invalid: no extension

229

230

// Own directory imports need specific patterns

231

import(`./${foo}.js`); // Invalid: too generic

232

import(`./module-${foo}.js`); // Valid: specific pattern

233

234

// Cannot contain wildcards

235

import(`./foo/*${bar}.js`); // Invalid: contains asterisk

236

```

237

238

## Supported Import Patterns

239

240

The plugin supports several dynamic import patterns:

241

242

### Template Literals

243

```javascript

244

import(`./locales/${locale}.js`); // -> './locales/*.js'

245

import(`./modules/${type}/${name}.js`); // -> './modules/*/*.js'

246

import(`./components-${variant}.js`); // -> './components-*.js'

247

import(`./modules-${name}/index.js`); // -> './modules-*/index.js'

248

```

249

250

### String Concatenation

251

```javascript

252

import('./locales/' + locale + '.js'); // -> './locales/*.js'

253

import('./src/' + folder + '/' + file); // -> './src/*/*.js'

254

import('./locales/' + locale + foo + bar + '.js'); // -> './locales/*.js'

255

import('./locales/' + `${locale}.js`); // -> './locales/*.js'

256

import('./locales/' + `${foo + bar}.js`); // -> './locales/*.js'

257

```

258

259

### Method Chaining

260

```javascript

261

import('./locales/'.concat(locale, '.js')); // -> './locales/*.js'

262

import('./base/'.concat(type, '/').concat(name, '.js')); // -> './base/*/*.js'

263

import('./'.concat(folder, '/').concat(name, '.js')); // -> './*/*.js'

264

```

265

266

### Import Assertions

267

Import assertions are fully preserved in the transformed code, allowing integration with other plugins:

268

269

```javascript

270

// Input - dynamic import with CSS assertion

271

import(`./styles/${sheet}.css`, { assert: { type: 'css' } });

272

273

// Output - each case preserves the assertion

274

function __variableDynamicImportRuntime0__(path) {

275

switch (path) {

276

case './styles/dark.css': return import('./styles/dark.css', { assert: { type: 'css' } });

277

case './styles/light.css': return import('./styles/light.css', { assert: { type: 'css' } });

278

default: return new Promise(function(resolve, reject) {

279

(typeof queueMicrotask === 'function' ? queueMicrotask : setTimeout)(

280

reject.bind(null, new Error("Unknown variable dynamic import: " + path))

281

);

282

});

283

}

284

}

285

```

286

287

This preservation enables compatibility with plugins like `rollup-plugin-import-css` that rely on import assertions to determine how to process different file types.

288

289

## Validation Rules

290

291

The plugin enforces several rules to ensure safe static analysis:

292

293

1. **Relative paths only**: Imports must start with `./` or `../`

294

2. **File extensions required**: Static parts must include file extensions

295

3. **Specific patterns for own directory**: Cannot use generic patterns in same directory

296

4. **Single-level globs**: Each variable becomes one `*`, limited to one level deep per directory (e.g., `import(\`./foo/\${x}\${y}/\${z}.js\`)` becomes `./foo/*/*.js`, not `./foo/**/*.js`)

297

5. **No wildcards in input**: Dynamic import strings cannot contain `*` characters

298

299

## Error Handling

300

301

The plugin provides flexible error handling through configuration options:

302

303

- **`warnOnError: false`** (default): Stops build on invalid patterns

304

- **`warnOnError: true`**: Issues warnings but continues build, leaving code unchanged

305

- **`errorWhenNoFilesFound: false`** (default): Continues when no files match glob

306

- **`errorWhenNoFilesFound: true`**: Throws error when glob matches no files

307

308

When `warnOnError` is `true` and `errorWhenNoFilesFound` is `true`, the plugin will warn instead of error for missing files.

309

310

## Types

311

312

```javascript { .api }

313

interface RollupDynamicImportVariablesOptions {

314

include?: FilterPattern;

315

exclude?: FilterPattern;

316

errorWhenNoFilesFound?: boolean;

317

warnOnError?: boolean;

318

}

319

320

type FilterPattern = string | RegExp | Array<string | RegExp> | null;

321

322

class VariableDynamicImportError extends Error {}

323

324

function dynamicImportToGlob(node: BaseNode, sourceString: string): string | null;

325

326

interface BaseNode {

327

type: string;

328

start?: number;

329

end?: number;

330

[key: string]: any;

331

}

332

333

interface Plugin {

334

name: string;

335

transform(code: string, id: string): TransformResult | null;

336

}

337

338

interface TransformResult {

339

code: string;

340

map: SourceMap;

341

}

342

343

interface SourceMap {

344

file: string;

345

includeContent: boolean;

346

hires: boolean;

347

}

348

```