or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

code-generation.mdcode-optimization.mdindex.mdmodule-system.mdplatform-inlining.mdrequire-optimization.md

require-optimization.mddocs/

0

# Require Optimization

1

2

Inlines top-level require() calls to enable lazy loading and reduce bundle overhead by replacing variable assignments with direct require() calls at usage sites.

3

4

## Capabilities

5

6

### Inline Requires Plugin

7

8

Transforms top-level require() assignments into inline require() calls for improved lazy loading and bundle performance.

9

10

```javascript { .api }

11

/**

12

* Creates a Babel plugin that inlines require() calls

13

* @returns Babel plugin object that processes require() assignments

14

*/

15

function inlineRequiresPlugin(): PluginObj<State>;

16

17

interface InlineRequiresPluginOptions {

18

/** Array of require calls to ignore (e.g., ['fs', 'path']) */

19

ignoredRequires?: ReadonlyArray<string>;

20

/** Function names that can be inlined (default: ['require']) */

21

inlineableCalls?: ReadonlyArray<string>;

22

/** Modules that should not be memoized even when memoizeCalls is true */

23

nonMemoizedModules?: ReadonlyArray<string>;

24

/** Whether to memoize repeated require() calls (default: false) */

25

memoizeCalls?: boolean;

26

}

27

28

interface State {

29

opts?: InlineRequiresPluginOptions;

30

ignoredRequires: Set<string>;

31

inlineableCalls: Set<string>;

32

membersAssigned: Map<string, Set<string>>;

33

}

34

```

35

36

**Usage Examples:**

37

38

```javascript

39

const babel = require("@babel/core");

40

const { inlineRequiresPlugin } = require("metro-transform-plugins");

41

42

const code = `

43

var fs = require('fs');

44

var path = require('path');

45

var lodash = require('lodash');

46

47

function readConfig() {

48

return fs.readFileSync('./config.json', 'utf8');

49

}

50

51

function processPath(inputPath) {

52

return path.join(inputPath, 'processed');

53

}

54

55

console.log(lodash.map([1, 2, 3], x => x * 2));

56

`;

57

58

const transformed = babel.transformSync(code, {

59

plugins: [

60

[inlineRequiresPlugin, {

61

ignoredRequires: ['fs'], // Don't inline fs module

62

memoizeCalls: true

63

}]

64

]

65

});

66

67

// Result:

68

// var fs = require('fs'); // Not inlined (in ignoredRequires)

69

// var _path;

70

// var _lodash;

71

//

72

// function readConfig() {

73

// return fs.readFileSync('./config.json', 'utf8');

74

// }

75

//

76

// function processPath(inputPath) {

77

// return (_path || (_path = require('path'))).join(inputPath, 'processed');

78

// }

79

//

80

// console.log((_lodash || (_lodash = require('lodash'))).map([1, 2, 3], x => x * 2));

81

```

82

83

### Simple Variable Inlining

84

85

Handles basic require() variable assignments:

86

87

```javascript { .api }

88

/**

89

* Simple require assignment inlining

90

* var module = require('module-name');

91

* module.method() → require('module-name').method()

92

*/

93

94

// Before transformation

95

var React = require('react');

96

var Component = React.Component;

97

function render() {

98

return React.createElement('div');

99

}

100

101

// After transformation

102

var Component = require('react').Component;

103

function render() {

104

return require('react').createElement('div');

105

}

106

```

107

108

### Member Expression Inlining

109

110

Inlines require() calls with property access:

111

112

```javascript { .api }

113

/**

114

* Member expression require inlining

115

* var member = require('module').property;

116

* member.method() → require('module').property.method()

117

*/

118

119

// Before transformation

120

var createElement = require('react').createElement;

121

var Fragment = require('react').Fragment;

122

123

function component() {

124

return createElement(Fragment, null, 'Hello');

125

}

126

127

// After transformation

128

function component() {

129

return require('react').createElement(require('react').Fragment, null, 'Hello');

130

}

131

```

132

133

### Destructuring Assignment Inlining

134

135

Handles ES6 destructuring patterns:

136

137

```javascript { .api }

138

/**

139

* Destructuring assignment inlining

140

* const {method} = require('module');

141

* method() → require('module').method()

142

*/

143

144

// Before transformation

145

const { useState, useEffect } = require('react');

146

const { join, resolve } = require('path');

147

148

function component() {

149

const [state, setState] = useState(0);

150

const configPath = join(__dirname, 'config.json');

151

return state;

152

}

153

154

// After transformation

155

function component() {

156

const [state, setState] = require('react').useState(0);

157

const configPath = require('path').join(__dirname, 'config.json');

158

return state;

159

}

160

```

161

162

### Memoized Require Calls

163

164

Optional memoization to avoid repeated module loading:

165

166

```javascript { .api }

167

/**

168

* Memoized require pattern (when memoizeCalls: true)

169

* Creates memoization variables for frequently used modules

170

*/

171

172

// Before transformation (with memoizeCalls: true)

173

var utils = require('./utils');

174

function a() { return utils.helper1(); }

175

function b() { return utils.helper2(); }

176

function c() { return utils.helper3(); }

177

178

// After transformation

179

var _utils;

180

function a() { return (_utils || (_utils = require('./utils'))).helper1(); }

181

function b() { return (_utils || (_utils = require('./utils'))).helper2(); }

182

function c() { return (_utils || (_utils = require('./utils'))).helper3(); }

183

```

184

185

### Require.resolve Support

186

187

Handles require.resolve() patterns for module resolution:

188

189

```javascript { .api }

190

/**

191

* require.resolve() call inlining

192

* var module = require(require.resolve('module-name'));

193

*/

194

195

// Before transformation

196

var config = require(require.resolve('./config'));

197

config.setting = 'value';

198

199

// After transformation

200

require(require.resolve('./config')).setting = 'value';

201

```

202

203

### Safety Checks and Exclusions

204

205

Implements safety mechanisms to prevent breaking transformations:

206

207

```javascript { .api }

208

/**

209

* Safety exclusions prevent incorrect inlining

210

*/

211

212

// Excluded: Modules with member assignments

213

var utils = require('./utils');

214

utils.cache = {}; // Member assignment detected - won't inline utils

215

216

// Excluded: Non-constant violations

217

var fs = require('fs');

218

fs = mockFs; // Reassignment - won't inline fs

219

220

// Excluded: Babel runtime modules (automatically)

221

var helper = require('@babel/runtime/helpers/something'); // Never inlined

222

223

// Excluded: Modules in ignoredRequires option

224

var path = require('path'); // Won't inline if 'path' in ignoredRequires

225

```

226

227

### Block-Level Optimization

228

229

Optimizes memoization based on code block structure:

230

231

```javascript { .api }

232

/**

233

* Block-level memoization optimization

234

* Uses different patterns based on code structure

235

*/

236

237

// Within same block - uses memoization variable

238

function sameBlock() {

239

const a = (_utils || (_utils = require('./utils'))).methodA();

240

const b = _utils.methodB(); // Reuses memoized variable

241

}

242

243

// Across different blocks - uses full memoization expression

244

function differentBlocks() {

245

if (condition) {

246

return (_utils || (_utils = require('./utils'))).methodA();

247

} else {

248

return (_utils || (_utils = require('./utils'))).methodB();

249

}

250

}

251

```

252

253

### Source Location Preservation

254

255

Maintains original source locations for debugging and error reporting:

256

257

```javascript { .api }

258

/**

259

* Source location tracking

260

* Preserves original require() call location information

261

*/

262

263

// Adds METRO_INLINE_REQUIRES_INIT_LOC metadata to inlined expressions

264

// This helps with:

265

// - Source map accuracy

266

// - Error stack trace precision

267

// - Debugging experience

268

```

269

270

### Custom Inlineable Calls

271

272

Supports custom function names beyond 'require':

273

274

```javascript { .api }

275

/**

276

* Custom inlineable function support

277

* @param inlineableCalls - Array of function names to inline

278

*/

279

280

// Configuration: inlineableCalls: ['require', 'load', 'import']

281

var module1 = require('module1'); // Inlined

282

var module2 = load('module2'); // Inlined

283

var module3 = import('module3'); // Inlined

284

var module4 = customLoader('module4'); // Not inlined

285

```

286

287

### Non-Memoized Modules

288

289

Prevents memoization for specific modules that should always be fresh:

290

291

```javascript { .api }

292

/**

293

* Non-memoized module handling

294

* @param nonMemoizedModules - Modules to never memoize

295

*/

296

297

// Configuration: nonMemoizedModules: ['./config', 'dotenv']

298

var config = require('./config'); // Always fresh, never memoized

299

var dotenv = require('dotenv'); // Always fresh, never memoized

300

var utils = require('./utils'); // Can be memoized (if memoizeCalls: true)

301

```

302

303

### Error Recovery

304

305

Graceful handling of transformation failures:

306

307

```javascript { .api }

308

/**

309

* Error recovery mechanism

310

* If replacement fails, keeps original require() assignment

311

*/

312

313

// If inlining fails (e.g., due to complex AST structure):

314

// - Logs the error internally

315

// - Preserves original require() assignment

316

// - Continues processing other requires

317

// - Prevents build failures from transformation issues

318

```