{"id":13447015,"url":"https://github.com/broccolijs/broccoli","last_synced_at":"2025-05-14T07:07:55.981Z","repository":{"id":8451665,"uuid":"10045915","full_name":"broccolijs/broccoli","owner":"broccolijs","description":"Browser compilation library – an asset pipeline for applications that run in the browser","archived":false,"fork":false,"pushed_at":"2025-04-10T06:12:21.000Z","size":2161,"stargazers_count":3325,"open_issues_count":55,"forks_count":216,"subscribers_count":69,"default_branch":"master","last_synced_at":"2025-05-07T06:59:02.547Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://broccoli.build","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/broccolijs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2013-05-14T02:48:01.000Z","updated_at":"2025-04-23T08:42:07.000Z","dependencies_parsed_at":"2024-11-19T00:06:45.398Z","dependency_job_id":"4186e6e4-0c1b-4142-bafe-e6fcb60d4d9f","html_url":"https://github.com/broccolijs/broccoli","commit_stats":{"total_commits":819,"total_committers":59,"mean_commits":13.88135593220339,"dds":"0.38339438339438336","last_synced_commit":"840149456de7d83bd8a5d41ac0fdd9e893101105"},"previous_names":[],"tags_count":102,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/broccolijs%2Fbroccoli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/broccolijs%2Fbroccoli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/broccolijs%2Fbroccoli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/broccolijs%2Fbroccoli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/broccolijs","download_url":"https://codeload.github.com/broccolijs/broccoli/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254092650,"owners_count":22013290,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T05:01:05.942Z","updated_at":"2025-05-14T07:07:55.962Z","avatar_url":"https://github.com/broccolijs.png","language":"JavaScript","readme":"# Broccoli\n\n\u003cimg src=\"logo/broccoli-logo.generated.png\" align=\"right\" height=\"150\"\u003e\n\n[![Build Status](https://github.com/broccolijs/broccoli/workflows/CI/badge.svg)](https://github.com/broccolijs/broccoli/actions)\n\nA fast, reliable asset pipeline, supporting constant-time rebuilds and compact\nbuild definitions. Comparable to the Rails asset pipeline in scope, though it\nruns on Node and is backend-agnostic. \n\nFor more information and guides/documentation, checkout [broccoli.build](http://broccoli.build)\n\nFor background and architecture, see the\n[introductory blog post](http://www.solitr.com/blog/2014/02/broccoli-first-release/).\n\nFor the command line interface, see\n[broccoli-cli](https://github.com/broccolijs/broccoli-cli).\n\n## Installation\n\n```bash\nnpm install --save-dev broccoli\nnpm install --global broccoli-cli\n```\n\n## Brocfile.js\n\nA `Brocfile.js` file in the project root contains the build specification. It\nshould export a function that returns a tree. Note: the Brocfile historically\ncould export a tree/string directly, however this is now deprecated in favor\nof a function that can receive [options](#options)\n\nA tree can be any string representing a directory path, like `'app'` or\n`'src'`. Or a tree can be an object conforming to the [Plugin API\nSpecification](#plugin-api-specification). A `Brocfile.js` will usually\ndirectly work with only directory paths, and then use the plugins in the\n[Plugins](#plugins) section to generate transformed trees.\n\nThe following simple `Brocfile.js` would export the `app/` subdirectory as a\ntree:\n\n```js\nexport default () =\u003e 'app';\n```\n\nWith that Brocfile, the build result would equal the contents of the `app`\ntree in your project folder. For example, say your project contains these\nfiles:\n\n    app\n    ├─ main.js\n    └─ helper.js\n    Brocfile.js\n    package.json\n    …\n\nRunning `broccoli build the-output` (a command provided by\n[broccoli-cli](https://github.com/broccolijs/broccoli-cli)) would generate\nthe following folder within your project folder:\n\n    the-output\n    ├─ main.js\n    └─ helper.js\n\n### Options\n\nThe function that is exported from `module.exports` is passed an options hash by Broccoli\nthat can be used when assembling the build.\n\nThe options hash is populated by the CLI environment when running `broccoli build`\nor `broccoli serve`. It currently only accepts a single option `--environment`, which\nis passed as `env` in the `options` hash.\n\nAdditionally `--prod` and `--dev` are available aliases to `--environment=production`\nand `--environment=development` respectively.\n\n* `options`:\n    * `env`: Defaults to `development`, and can be overridden with the CLI argument `--environment=X`\n\nFor example:\n```js\nexport default (options) =\u003e {\n    // tree = ... assemble tree\n\n    // In production environment, minify the files\n    if (options.env === 'production') {\n        tree = minify(tree);\n    }\n\n    return tree;\n}\n```\n\n### TypeScript Support\n\nA `Brocfile.ts` can be used in place of a `Brocfile.js` and Broccoli will automatically parse this\nthrough [ts-node](https://www.npmjs.com/package/ts-node) to provide [TypeScript](https://www.typescriptlang.org)\nsupport. This allows developers to leverage type information when assembling a build pipeline. By default,\nBroccoli provides [type information](lib/index.d.ts) for the [options](#options) object passed to the build function.\n\n```ts\nimport { BrocfileOptions } from 'broccoli';\n\nexport default (options: BrocfileOptions) =\u003e {\n  // tree = ... assemble tree\n\n  // In production environment, minify the files\n  if (options.env === 'production') {\n    tree = minify(tree);\n  }\n\n  return tree;\n};\n\n```\n\nTypescript by default only allows the [ES6 modules](https://nodejs.org/api/esm.html) `import/export` syntax to work\nwhen importing ES6 modules. In order to import a CommonJS module (one that uses `require() or module.exports`, you must\nuse the following syntax:\n\n```ts\nimport foo = require('foo');\n\nexport = 'bar';\n```\n\nYou'll note the syntax is slightly different from the ESM syntax, but reads fairly well.\n\n### Using plugins in a `Brocfile.js`\n\nThe following `Brocfile.js` exports the `app/` subdirectory as `appkit/`:\n\n```js\n// Brocfile.js\nimport Funnel from 'broccoli-funnel';\n\nexport default () =\u003e new Funnel('app', {\n  destDir: 'appkit'\n})\n```\n\nBroccoli supports [ES6 modules](https://nodejs.org/api/esm.html) via [esm](https://www.npmjs.com/package/esm) for\n`Brocfile.js`. Note, TypeScript requires the use of a different syntax, see the TypeScript section above.\n\nYou can also use regular CommonJS `require` and `module.exports` if you prefer, however ESM is the future of Node,\nand the recommended syntax to use.\n\nThat example uses the plugin [`broccoli-funnel`](https://www.npmjs.com/package/broccoli-funnel).\nIn order for the `import` call to work, you must first put the plugin in your `devDependencies` and install it, with\n\n    npm install --save-dev broccoli-funnel\n\nWith the above `Brocfile.js` and the file tree from the previous example,\nrunning `broccoli build the-output` would generate the following folder:\n\n    the-output\n    └─ appkit\n       ├─ main.js\n       └─ helper.js\n\n## Plugins\n\nYou can find plugins under the [broccoli-plugin keyword](https://www.npmjs.org/browse/keyword/broccoli-plugin) on npm.\n\n## Using Broccoli Programmatically\n\nIn addition to using Broccoli via the combination of `broccoli-cli` and a `Brocfile.js`, you can also use Broccoli programmatically to construct your own build output via the `Builder` class. The `Builder` is one of the core APIs in Broccoli, and is responsible for taking a graph of Broccoli nodes and producing an actual build artifact (i.e. the output usually found in your `dist` directory after you run `broccoli build`). The output of a `Builder`'s `build` method is a Promise that resolves when all the operations in the graph are complete. You can use this promise to chain together additional operations (such as error handling or cleanup) that will execute once the build step is complete.\n\nBy way of example, let's assume we have a graph of Broccoli nodes constructed via a combination of `Funnel` and `MergeTrees`:\n\n```js\n// non Brocfile.js, regular commonjs\nconst Funnel = require('broccoli-funnel');\nconst MergeTrees = require('broccoli-merge-trees');\n\nconst html = new Funnel(appRoot, {\n  files: ['index.html'],\n  annotation: 'Index file'\n})\n\nconst js = new Funnel(appRoot, {\n  files: ['app.js'],\n  destDir: '/assets',\n  annotation: 'JS Files'\n});\n\nconst css = new Funnel(appRoot, {\n  srcDir: 'styles',\n  files: ['app.css'],\n  destDir: '/assets',\n  annotation: 'CSS Files'\n});\n\nconst public = new Funnel(appRoot, {\n  annotation: 'Public Files'\n});\n\nconst tree = new MergeTrees([html, js, css, public]);\n```\n\nAt this point, `tree` is a graph of nodes, each of which can represent either an input or a transformation that we want to perform. In other words, `tree` is an abstract set of operations, *not* a concrete set of output files.\n\nIn order to perform all the operations described in `tree`, we need to do the following:\n- construct a `Builder` instance, passing in the graph we constructed before\n- call the `build` method, which will traverse the graph, performing each operation and eventually writing the output to a temporary folder indicated by `builder.outputPath`\n\nSince we typically want do more than write to a temporary folder, we'll also use a library called `TreeSync` to sync the contents of the temp file with our desired output directory. Finally, we'll clean up the temporary folder once all our operations are complete:\n\n```js\nconst { Builder } = require('broccoli');\nconst TreeSync = require('tree-sync');\nconst MergeTrees = require('broccoli-merge-trees');\n// ...snip...\nconst tree = new MergeTrees([html, js, css, public]);\n\nconst builder = new Builder(tree);\n\nconst outputDir = 'dist';\nconst outputTree = new TreeSync(builder.outputPath, outputDir);\n\nbuilder.build()\n  .then(() =\u003e {\n    // Calling `sync` will synchronize the contents of the builder's `outPath` with our output directory.\n    return outputTree.sync();\n  })\n  .then(() =\u003e {\n    // Now that we're done with the build, clean up any temporary files were created\n    return builder.cleanup();\n  })\n  .catch(err =\u003e {\n    // In case something in this process fails, we still want to ensure that we clean up the temp files\n    console.log(err);\n    return builder.cleanup();\n  });\n```\n\n### Running Broccoli, Directly or Through Other Tools\n\n* [broccoli-timepiece](https://github.com/rjackson/broccoli-timepiece)\n* [grunt-broccoli](https://github.com/embersherpa/grunt-broccoli)\n* [grunt-broccoli-build](https://github.com/ericf/grunt-broccoli-build)\n\n### Helpers\n\nShared code for writing plugins.\n\n* [broccoli-plugin](https://github.com/broccolijs/broccoli-plugin)\n* [broccoli-caching-writer](https://github.com/rjackson/broccoli-caching-writer)\n* [broccoli-filter](https://github.com/broccolijs/broccoli-filter)\n\n## Plugin API Specification\n\nSee [docs/node-api.md](docs/node-api.md).\n\nAlso see [docs/broccoli-1-0-plugin-api.md](docs/broccoli-1-0-plugin-api.md) on\nhow to upgrade from Broccoli 0.x to the Broccoli 1.x API.\n\n## Security\n\n* Do not run `broccoli serve` on a production server. While this is\n  theoretically safe, it exposes a needlessly large amount of attack surface\n  just for serving static assets. Instead, use `broccoli build` to precompile\n  your assets, and serve the static files from a web server of your choice.\n\n## Get Help\n\n* IRC: `#broccolijs` on Freenode. Ask your question and stick around for a few\n  hours. Someone will see your message eventually.\n* Twitter: mention @jo_liss with your question\n* GitHub: Open an issue on a specific plugin repository, or on this\n  repository for general questions.\n\n## License\n\nBroccoli was originally written by [Jo Liss](http://www.solitr.com/) and is\nlicensed under the [MIT license](LICENSE).\n\nThe Broccoli logo was created by [Samantha Penner\n(Miric)](http://mirics.deviantart.com/) and is licensed under [CC0\n1.0](https://creativecommons.org/publicdomain/zero/1.0/).\n","funding_links":[],"categories":["Packages","JavaScript","Repository","包","Build tools","目录"],"sub_categories":["Build tools","Build Tools","构建工具"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbroccolijs%2Fbroccoli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbroccolijs%2Fbroccoli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbroccolijs%2Fbroccoli/lists"}