or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

additional-utilities.mdasset-management.mdexecutors.mdgenerators.mdindex.mdpackage-management.mdtypescript-utilities.md

asset-management.mddocs/

0

# Asset Management

1

2

@nx/js provides comprehensive static asset handling capabilities for copying, processing, and managing non-code files during the build process with support for glob patterns, watch mode, and flexible output configuration.

3

4

## Capabilities

5

6

### Asset Copying

7

8

High-performance asset copying with glob pattern support, filtering, and flexible input/output mapping.

9

10

```typescript { .api }

11

/**

12

* Copies static assets from source to destination with glob pattern support

13

* @param options - Asset copying configuration options

14

* @param context - Nx executor context for project information

15

* @returns Promise resolving to copy result with success status and optional cleanup

16

*/

17

function copyAssets(

18

options: CopyAssetsOptions,

19

context: ExecutorContext

20

): Promise<CopyAssetsResult>;

21

22

interface CopyAssetsOptions {

23

assets: Array<AssetGlob | string>; // Asset patterns or simple paths

24

outputPath: string; // Base output directory

25

watchMode?: WatchMode; // Optional watch mode configuration

26

}

27

28

interface CopyAssetsResult {

29

success: boolean; // Whether copy operation succeeded

30

stop?(): void; // Optional cleanup function for watch mode

31

}

32

33

interface WatchMode {

34

onCopy?: (files: string[]) => void; // Callback for when files are copied

35

}

36

```

37

38

**Usage Examples:**

39

40

```typescript

41

import { copyAssets } from "@nx/js";

42

43

// Basic asset copying

44

const result = await copyAssets({

45

assets: [

46

'src/assets/**/*', // Simple glob pattern

47

'README.md', // Single file

48

{

49

input: 'src/docs', // Source directory

50

output: './documentation', // Destination directory

51

glob: '**/*.md' // File pattern

52

}

53

],

54

outputPath: 'dist/my-app'

55

}, context);

56

57

// With watch mode

58

const watchResult = await copyAssets({

59

assets: ['src/assets/**/*'],

60

outputPath: 'dist/my-app',

61

watchMode: {

62

onCopy: (files) => {

63

console.log(`Copied ${files.length} files`);

64

}

65

}

66

}, context);

67

68

// Cleanup watcher when done

69

if (watchResult.stop) {

70

watchResult.stop();

71

}

72

```

73

74

### Asset Glob Processing

75

76

Converts asset glob patterns and configurations into concrete file input/output mappings.

77

78

```typescript { .api }

79

/**

80

* Converts asset globs to concrete file input/output mappings

81

* @param assets - Array of asset patterns or configurations

82

* @param rootDir - Root directory for resolving relative paths

83

* @param outDir - Base output directory for assets

84

* @returns Array of file input/output mappings

85

*/

86

function assetGlobsToFiles(

87

assets: Array<AssetGlob | string>,

88

rootDir: string,

89

outDir: string

90

): FileInputOutput[];

91

92

interface FileInputOutput {

93

input: string; // Source file path

94

output: string; // Destination file path

95

}

96

97

interface AssetGlob extends FileInputOutput {

98

glob: string; // Glob pattern for matching files

99

ignore?: string[]; // Patterns to ignore

100

dot?: boolean; // Include dotfiles (default: false)

101

includeIgnoredFiles?: boolean; // Include files ignored by .gitignore

102

}

103

```

104

105

**Usage Examples:**

106

107

```typescript

108

import { assetGlobsToFiles } from "@nx/js";

109

110

// Convert asset configurations to file mappings

111

const fileMap = assetGlobsToFiles([

112

'src/assets/**/*', // Simple pattern

113

{

114

input: 'src/images', // Source directory

115

output: './assets/images', // Output directory

116

glob: '**/*.{png,jpg,gif}', // Image files only

117

ignore: ['**/*.tmp'], // Ignore temporary files

118

dot: false // Exclude dotfiles

119

},

120

{

121

input: 'docs',

122

output: './documentation',

123

glob: '**/*.md',

124

includeIgnoredFiles: true // Include gitignored files

125

}

126

], 'libs/my-lib', 'dist/libs/my-lib');

127

128

// Results in array like:

129

// [

130

// { input: 'libs/my-lib/src/assets/logo.png', output: 'dist/libs/my-lib/logo.png' },

131

// { input: 'libs/my-lib/src/images/hero.jpg', output: 'dist/libs/my-lib/assets/images/hero.jpg' },

132

// { input: 'libs/my-lib/docs/README.md', output: 'dist/libs/my-lib/documentation/README.md' }

133

// ]

134

```

135

136

## Asset Configuration Types

137

138

### Simple String Patterns

139

140

Use simple glob strings for basic asset copying:

141

142

```typescript

143

const assets = [

144

'src/assets/**/*', // All files in assets directory

145

'*.md', // All markdown files in root

146

'public/**/*.{html,css,js}' // Web assets

147

];

148

```

149

150

### Advanced Asset Globs

151

152

Use AssetGlob objects for precise control over asset handling:

153

154

```typescript

155

const assets: AssetGlob[] = [

156

{

157

input: 'src/assets', // Source directory

158

output: './static', // Output subdirectory

159

glob: '**/*', // All files recursively

160

ignore: ['**/*.tmp', '**/.DS_Store'], // Ignore patterns

161

dot: false, // Exclude dotfiles

162

includeIgnoredFiles: false // Respect .gitignore

163

},

164

{

165

input: 'src/translations',

166

output: './i18n',

167

glob: '*.json', // JSON files only

168

dot: true, // Include dotfiles

169

includeIgnoredFiles: true // Include ignored files

170

}

171

];

172

```

173

174

### Mixed Asset Configurations

175

176

Combine simple strings and detailed configurations:

177

178

```typescript

179

const assets = [

180

'README.md', // Simple file copy

181

'LICENSE', // Another simple file

182

{

183

input: 'src/assets', // Detailed configuration

184

output: './assets',

185

glob: '**/*.{png,jpg,svg}',

186

ignore: ['**/*-temp.*']

187

},

188

'src/styles/**/*.css' // Simple glob pattern

189

];

190

```

191

192

## Asset Management Patterns

193

194

### Build-Time Asset Processing

195

196

Copy different assets based on build configuration:

197

198

```typescript

199

// Development assets (includes source maps, unminified files)

200

const devAssets = [

201

'src/assets/**/*',

202

'src/styles/**/*.css',

203

'src/scripts/**/*.js'

204

];

205

206

// Production assets (optimized, compressed)

207

const prodAssets = [

208

{

209

input: 'src/assets',

210

output: './assets',

211

glob: '**/*.{png,jpg,svg,webp}', // Image assets only

212

ignore: ['**/*-dev.*'] // Exclude development assets

213

},

214

{

215

input: 'dist/styles', // Pre-processed styles

216

output: './styles',

217

glob: '*.min.css' // Minified CSS only

218

}

219

];

220

```

221

222

### Conditional Asset Inclusion

223

224

Include different assets based on environment or configuration:

225

226

```typescript

227

const baseAssets = ['README.md', 'LICENSE'];

228

229

const environmentAssets = process.env.NODE_ENV === 'production'

230

? [

231

{

232

input: 'src/assets/prod',

233

output: './assets',

234

glob: '**/*'

235

}

236

]

237

: [

238

{

239

input: 'src/assets/dev',

240

output: './assets',

241

glob: '**/*',

242

includeIgnoredFiles: true

243

}

244

];

245

246

const allAssets = [...baseAssets, ...environmentAssets];

247

```

248

249

### Watch Mode Integration

250

251

Use asset copying with file watching for development:

252

253

```typescript

254

import { copyAssets } from "@nx/js";

255

256

const setupAssetWatcher = async () => {

257

const result = await copyAssets({

258

assets: ['src/assets/**/*'],

259

outputPath: 'dist/my-app',

260

watchMode: {

261

onCopy: (files) => {

262

console.log(`Asset update: ${files.length} files copied`);

263

// Trigger other processes like live reload

264

notifyLiveReload();

265

}

266

}

267

}, context);

268

269

// Return cleanup function

270

return () => {

271

if (result.stop) {

272

result.stop();

273

}

274

};

275

};

276

277

// Use in development server

278

const stopWatching = await setupAssetWatcher();

279

280

// Cleanup on exit

281

process.on('SIGINT', () => {

282

stopWatching();

283

process.exit(0);

284

});

285

```

286

287

### Asset Organization Strategies

288

289

Organize assets by type, environment, or feature:

290

291

```typescript

292

// By asset type

293

const assetsByType = [

294

{

295

input: 'src/images',

296

output: './assets/images',

297

glob: '**/*.{png,jpg,jpeg,gif,svg,webp}',

298

ignore: ['**/*-temp.*']

299

},

300

{

301

input: 'src/fonts',

302

output: './assets/fonts',

303

glob: '**/*.{woff,woff2,ttf,eot}',

304

dot: false

305

},

306

{

307

input: 'src/data',

308

output: './assets/data',

309

glob: '**/*.{json,csv,xml}',

310

includeIgnoredFiles: false

311

}

312

];

313

314

// By feature or module

315

const assetsByFeature = [

316

{

317

input: 'src/modules/dashboard/assets',

318

output: './assets/dashboard',

319

glob: '**/*'

320

},

321

{

322

input: 'src/modules/profile/assets',

323

output: './assets/profile',

324

glob: '**/*'

325

}

326

];

327

```

328

329

### Integration with Build Tools

330

331

Combine asset copying with other build processes:

332

333

```typescript

334

// In an executor or build script

335

const buildWithAssets = async (options, context) => {

336

// 1. Clean output directory

337

await fs.remove(options.outputPath);

338

339

// 2. Compile TypeScript/JavaScript

340

await compileCode(options, context);

341

342

// 3. Copy assets

343

const assetResult = await copyAssets({

344

assets: options.assets,

345

outputPath: options.outputPath

346

}, context);

347

348

// 4. Generate package.json

349

if (options.generatePackageJson) {

350

await generatePackageJson(options, context);

351

}

352

353

return {

354

success: assetResult.success

355

};

356

};

357

```

358

359

## Error Handling

360

361

Asset operations include comprehensive error handling:

362

363

```typescript

364

try {

365

const result = await copyAssets({

366

assets: ['src/assets/**/*'],

367

outputPath: 'dist/my-app'

368

}, context);

369

370

if (!result.success) {

371

console.error('Asset copying failed');

372

process.exit(1);

373

}

374

} catch (error) {

375

console.error('Asset copying error:', error.message);

376

// Handle specific error types

377

if (error.code === 'ENOENT') {

378

console.error('Source asset directory not found');

379

}

380

process.exit(1);

381

}

382

```