{"id":15841,"library":"substance-bundler","title":"Substance Bundler","description":"Substance Bundler is a custom JavaScript bundling and build orchestration library, currently at version `0.27.4`. It offers a high-level, shell-script-like approach to defining build processes, distinguishing itself from traditional task runners like Gulp or Grunt by emphasizing simplicity and direct action execution. The library internally leverages `chokidar` for robust file watching, ensuring all defined operations automatically react to source file changes. While not a bundler itself, it seamlessly integrates with popular tools such as Webpack, Rollup, and PostCSS via dedicated extensions, acting as an orchestrator for these underlying technologies. This allows developers to define complex build pipelines, including copying files, removing directories, and executing custom scripts, all within a unified task-based system with inter-task dependencies. Its primary differentiator lies in its low-ceremony API for defining build steps and its integrated watch mode across all tasks, offering a streamlined development experience for projects that require custom but maintainable build logic.","status":"active","version":"0.27.4","language":"javascript","source_language":"en","source_url":"https.//github.com/substance/bundler","tags":["javascript"],"install":[{"cmd":"npm install substance-bundler","lang":"bash","label":"npm"},{"cmd":"yarn add substance-bundler","lang":"bash","label":"yarn"},{"cmd":"pnpm add substance-bundler","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required if using `substance-bundler/extensions/webpack` to integrate Webpack into build tasks.","package":"webpack","optional":true},{"reason":"Required if using `substance-bundler/extensions/rollup` to integrate Rollup into build tasks.","package":"rollup","optional":true},{"reason":"Required if using `substance-bundler/extensions/postcss` to integrate PostCSS into build tasks.","package":"postcss","optional":true}],"imports":[{"note":"The main bundler export is a CommonJS module. ESM `import` syntax will cause runtime errors.","wrong":"import b from 'substance-bundler'","symbol":"b","correct":"const b = require('substance-bundler')"},{"note":"Extensions are also CommonJS modules. Use `require()` to import them correctly.","wrong":"import { postcss } from 'substance-bundler/extensions/postcss'","symbol":"postcss","correct":"const postcss = require('substance-bundler/extensions/postcss')"},{"note":"Extensions are also CommonJS modules. Use `require()` to import them correctly.","wrong":"import rollup from 'substance-bundler/extensions/rollup'","symbol":"rollup","correct":"const rollup = require('substance-bundler/extensions/rollup')"}],"quickstart":{"code":"const b = require('substance-bundler');\nconst postcss = require('substance-bundler/extensions/postcss');\nconst rollup = require('substance-bundler/extensions/rollup');\n\n// Define a task to clean the build output directory\nb.task('clean', () => {\n  b.rm('dist');\n  console.log('Removed dist directory.');\n});\n\n// Define a task to compile CSS using PostCSS extension\nb.task('css', () => {\n  console.log('Bundling CSS...');\n  postcss(b, {\n    from: 'styles/index.css', // Assumes 'styles/index.css' exists\n    to: 'dist/app.css'\n  });\n});\n\n// Define a task to bundle JavaScript using Rollup extension\n// Requires a rollup.config.js and an entry point like index.js\nb.task('js', () => {\n  console.log('Bundling JavaScript with Rollup...');\n  // For a runnable example, ensure rollup.config.js and index.js exist\n  const rollupConfig = require('./rollup.config.js'); \n  rollup(b, rollupConfig);\n});\n\n// Define a task to copy static assets\nb.task('copy-assets', () => {\n  console.log('Copying assets...');\n  b.copy('./assets', 'dist/assets/'); // Assumes an 'assets' directory exists\n});\n\n// Define the default task which runs other tasks sequentially\nb.task('default', ['clean', 'css', 'js', 'copy-assets'], () => {\n  console.log('All default tasks completed!');\n});\n\n// Basic CLI runner (for demonstration, not part of bundler API itself)\nconst tasksToRun = process.argv.slice(2).filter(arg => !arg.startsWith('-'));\nconst watchMode = process.argv.includes('-w');\n\nif (watchMode) {\n  console.log('Running in watch mode...');\n  b.run(tasksToRun.length > 0 ? tasksToRun : ['default'], { watch: true });\n} else {\n  b.run(tasksToRun.length > 0 ? tasksToRun : ['default']);\n}\n\n// To run this script: \n// 1. Save as `make.js`.\n// 2. Create dummy `dist`, `styles`, `assets` directories. \n// 3. Create dummy `styles/index.css`, `index.js`, `rollup.config.js`.\n// 4. `npm install --save-dev rollup postcss @rollup/plugin-node-resolve`\n// 5. Execute: `node make.js` or `node make.js -w`","lang":"javascript","description":"This `make.js` script demonstrates defining and orchestrating multiple build tasks, including cleaning, CSS compilation via PostCSS, JavaScript bundling with Rollup, and file copying, all managed by `substance-bundler`. It showcases task dependencies and a basic command-line runner for build operations."},"warnings":[{"fix":"Always use `const b = require('substance-bundler')` and `const extension = require('substance-bundler/extensions/...')` in your build scripts. Ensure your script is treated as a CommonJS module.","message":"`substance-bundler` is published as a CommonJS module. Attempting to import it using ESM `import` syntax will result in runtime errors (e.g., `TypeError: require is not a function`) in Node.js environments configured for ESM.","severity":"breaking","affected_versions":">=0.1.0"},{"fix":"Ensure you `npm install --save-dev <package-name>` (e.g., `rollup`, `webpack`, `postcss`) for any extensions you use in your build tasks.","message":"When utilizing bundler extensions such as `rollup`, `webpack`, or `postcss`, their respective npm packages must be installed as peer/development dependencies in your project. `substance-bundler` itself does not bundle these external tools.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"For `b.copy` operations involving glob patterns, explicitly define `options.root` to specify the base directory from which source files are resolved.","message":"When using `b.copy` with glob patterns, especially when copying files to a new directory structure or renaming them, the `options.root` parameter is crucial. Failing to specify `root` can lead to incorrect destination paths, files being placed in unintended locations, or the glob pattern failing to match as expected.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Replace `fs.writeFileSync(path, data)` with `api.writeFileSync(path, data)` and similar `fs` calls with `api` methods within `b.custom` task `execute` functions to ensure proper bundler integration.","message":"Inside a `b.custom` task's `execute` function, direct usage of Node.js `fs` module operations (e.g., `fs.writeFileSync`) is generally discouraged. Instead, use the `api` object provided as the second argument (e.g., `api.writeFileSync`), which integrates with `substance-bundler`'s file watching and change propagation mechanisms.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Change your import statement to `const b = require('substance-bundler')`. If your entire project is ESM, you might need to wrap your `substance-bundler` script in a CommonJS context or adjust your module resolution.","cause":"Attempting to use ESM `import` syntax (e.g., `import b from 'substance-bundler'`) to load `substance-bundler` in an environment configured for ESM (e.g., `\"type\": \"module\"` in `package.json`).","error":"TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension \".js\" for .../node_modules/substance-bundler/index.js"},{"fix":"Install the missing package as a development dependency: `npm install --save-dev rollup` (or `webpack`, `postcss`).","cause":"You are using a `substance-bundler` extension (e.g., `substance-bundler/extensions/rollup`) but have not installed the corresponding external package (`rollup`) in your project's `node_modules`.","error":"Error: Cannot find module 'rollup' (or 'webpack', 'postcss')"},{"fix":"Ensure your 'clean' task (e.g., `b.rm('dist')`) is configured as a dependency and runs before tasks that create build output directories, or explicitly add logic to skip directory creation if it already exists.","cause":"A task (e.g., `b.custom` or `b.copy`) attempts to create a directory (`dist`) that already exists, and the operation is not configured to handle existing directories idempotently. This often happens if a 'clean' task (which removes `dist`) is not run or fails before other tasks that create `dist`.","error":"[bundler] Task 'clean' failed: Error: EEXIST: file already exists, mkdir 'dist'"},{"fix":"Verify that the glob pattern in your `src` path is correct, that the specified directory exists, and that the intended source files are present at that location relative to your `make.js` script.","cause":"A `b.copy` or `b.custom` task with a glob pattern (`styles/**/*.css`) cannot find any files matching the specified pattern, likely due to a typo in the path, incorrect relative pathing, or the files not existing at the given location.","error":"(node:12345) UnhandledPromiseRejectionWarning: Error: No input files found for pattern: styles/**/*.css"}],"ecosystem":"npm"}