{"id":13432511,"url":"https://github.com/saguijs/sagui","last_synced_at":"2025-10-02T23:35:41.353Z","repository":{"id":12546008,"uuid":"15216146","full_name":"saguijs/sagui","owner":"saguijs","description":":monkey: Front-end tooling in a single dependency","archived":true,"fork":false,"pushed_at":"2019-09-24T20:35:55.000Z","size":2032,"stargazers_count":670,"open_issues_count":35,"forks_count":32,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-01-17T10:35:58.224Z","etag":null,"topics":["babel","flowtype","jsx","minimalist","tooling","webpack"],"latest_commit_sha":null,"homepage":"http://sagui.js.org/","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/saguijs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-12-16T03:22:36.000Z","updated_at":"2024-12-01T16:31:46.000Z","dependencies_parsed_at":"2022-09-23T07:50:59.966Z","dependency_job_id":null,"html_url":"https://github.com/saguijs/sagui","commit_stats":null,"previous_names":[],"tags_count":154,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saguijs%2Fsagui","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saguijs%2Fsagui/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saguijs%2Fsagui/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saguijs%2Fsagui/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/saguijs","download_url":"https://codeload.github.com/saguijs/sagui/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235051566,"owners_count":18928185,"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":["babel","flowtype","jsx","minimalist","tooling","webpack"],"created_at":"2024-07-31T02:01:12.589Z","updated_at":"2025-10-02T23:35:40.988Z","avatar_url":"https://github.com/saguijs.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","Alternatives"],"sub_categories":[],"readme":"## Deprecated\n\nWhen Sagui was created, the frontend landscape was in a much different situation than it is today. Creating projects was a hell and we all faced the now infamous \"JavaScript fatigue\". Fast-forward to 2019 and we now have established solutions such as [create-react-app](https://github.com/facebook/create-react-app) that have a large community behind and is being well maintained. Therefore there is no longer a need for Sagui to exist.\n\nThis was a fantastic ride and I've learned a lot while building this little tool.\n\nThanks to all the community who help me along the way! ❤️🐒\n\n![Sagui](https://raw.githubusercontent.com/saguijs/sagui/master/banner.jpg)\n\n[![Build Status](https://travis-ci.org/saguijs/sagui.svg)](https://travis-ci.org/saguijs/sagui)\n[![Windows Tests](https://img.shields.io/appveyor/ci/pirelenito/sagui.svg?label=Windows%20Tests)](https://ci.appveyor.com/project/pirelenito/sagui)\n[![npm version](https://badge.fury.io/js/sagui.svg)](https://badge.fury.io/js/sagui)\n[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard)\n[![Join the chat at https://gitter.im/saguijs/sagui](https://badges.gitter.im/saguijs/sagui.svg)](https://gitter.im/saguijs/sagui?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n\nSagui is the **single development dependency** that provides the tooling required to build, test and develop modern JavaScript applications.\n\nIts main goal is to kill the need of global CLIs and boilerplates, making a reproducible and easily updated environment across projects.\n\nIt follows an opinionated convention over configuration approach, providing a solid foundation so that you can focus on writing your code and not your tooling.\n\n## Quick start in 3 steps!\n\nLet's create a new front-end project from scratch.\n\n**In a new folder**, create a [new npm project](https://docs.npmjs.com/cli/init):\n\n```bash\nnpm init -y\n```\n\n**Install Sagui locally** as a development dependency:\n\n```bash\nnpm install --save-dev sagui\n```\n\nStart the development server:\n\n```bash\nnpm start\n```\n\nDone! Sagui is an *auto-bootstraping* library, so during the install process (in a fresh npm project) it automatically creates a basic project scaffolding:\n\n```bash\n├── .editorconfig\n├── .flowconfig\n├── .gitignore\n├── sagui.config.js\n└── src\n    ├── index.html\n    ├── index.js\n    ├── index.css\n    └── index.spec.js\n```\n\nJust start writing the code inside the `src/` folder.\n\n## npm scripts\n\nSagui manages the [package.json](https://docs.npmjs.com/files/package.json) scripts for you:\n\n- `npm run build`: build a development version of the project;\n- `npm run dist`: build an optimized (ready for deployment) version of the project;\n- `npm run start`: spin up a development server with live-reload and [HMR](https://webpack.js.org/concepts/hot-module-replacement/);\n- `npm run format`: automatically format the code using [prettier](https://github.com/prettier/prettier);\n- `npm run test`: run all test related scripts below;\n- `npm run test:lint`: run static analysis in the code;\n- `npm run test:unit`: run the unit tests;\n- `npm run test:typecheck`: run the static type analysis in the code;\n- `npm run test:unit:watch`: run a test watcher (great for development and debugging).\n\nIf you don't change the scripts, they will be **automatically updated** on new Sagui releases.\n\n## Features\n\nAs stated earlier, Sagui strives to provide all the basic needs to create modern JavaScript applications.\n\n### Development server\n\nThe development server out-of-the-box has live reloading and **hot-module replacement**.\n\n### Build\n\nSagui uses [Webpack](https://webpack.js.org/) as its underlying bundling tool. The biggest feature that Webpack provides is that everything is a module. Sagui supports the following module types by default:\n\n- Fonts (`.woff`, `.woff2`, `.ttf`, `.eot`, `.otf`)\n- HTML (`.html`)\n- Images (`.png`, `.jpg`, `.jpeg`, `.gif`, `.svg`)\n- JavaScript (`.js`, `.es6`, `.jsx`) via [Babel]((http://babeljs.io/docs/learn-es2015/))\n- JSON\n- Styles in [CSS Modules](https://github.com/css-modules) in either plain CSS or [Sass lang](http://sass-lang.com/)\n- Text (`.txt`) files [loaded](https://github.com/webpack/raw-loader) without any processing\n- Video (`.ogg`, `.mp4`)\n- YAML\n\nDuring build, optimizations and special processing are also performed in the output bundle:\n\n- [Autoprefixer for CSS properties](https://github.com/postcss/autoprefixer) for cross-browser support;\n- [Commons code splitting](https://webpack.js.org/plugins/commons-chunk-plugin/) if there is more than a single entry-point;\n- [Extract styles as separated files](https://github.com/webpack/extract-text-webpack-plugin) to style the page before the JavaScript is loaded and parsed;\n- Minification and code dedupication.\n\n### Testing and quality\n\nTest automation in Sagui is achieved by creating `.spec.js` files inside the `src/` folder using the [Jasmine](http://jasmine.github.io/) framework.\n\nA simple example would be:\n\n- `src/components/button.js`\n- `src/components/button.spec.js`\n\nSagui will automatically run every test file that follows this convention.\n\nUnder the hood it uses [Karma test runner](http://karma-runner.github.io/) to allow running the tests in the most diverse browsers and even through [Selenium](http://docs.seleniumhq.org/) (not natively).\n\nTo run the tests Sagui uses [Chrome Headless](https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md), but it fallbacks to [PhantomJS](http://phantomjs.org/) if Chrome is not installed on the machine.\n\nMake sure either of these browsers is installed to be able to run the tests:\n\n- [Chrome](https://www.google.com/chrome/browser/desktop/index.html)\n- [PhantomJS](https://github.com/Medium/phantomjs#using-phantomjs-from-disk)\n\nTo open the tests in a browser (or in multiple browsers!), simply follow the link Karma outputs when you start running the script `test:unit:watch`. Running them in a browser allows you to set breakpoints and debug your code properly. Note watch mode is necessary, else tests will stop running when finished.\n\n#### Code formatting\n\nWe expect the code to be formatted using [prettier](https://github.com/prettier/prettier). Sagui has a script that can apply the expected code format for you, simply run:\n\n```bash\nnpm run format\n```\n\nTo get the code formatted automatically for you, it is recommended that you install the [prettier plugin](https://atom.io/packages/prettier-atom) in your editor of choice with the same configuration that is used by Sagui:\n\n- singleQuote: `true`\n- parser: `babylon`\n- semi: `false`\n- printWidth: `100`\n- trailingComma: `es5`\n\nPrettier is combined with the [JavaScript Standard Style](http://standardjs.com/) convention to check for common errors in the code.\n\n#### Static type checking\n\n[Flowtype](flowtype.org) static type analysis is available as part of the testing suite. By default the flowtype checker only runs on files with the `// @flow` comment at the beginning, so no static type analysis will be actually performed unless you add that. See the [docs](https://flowtype.org/docs/existing.html) for an more in depth explanation of why it is a good idea to have it like this.\n\nSagui bundles loose lib [interface declarations](https://flowtype.org/docs/declarations.html#pointing-your-project-to-declarations) for the Jasmine APIs used in the tests. You might want to look into the more complete [flow-typed](https://github.com/flowtype/flow-typed) repo to get already made interfaces for common project dependencies such as React, Redux, Ramda, …\n\n## Configuration\n\nThe Sagui configuration is all performed via the single `sagui.config.js` that is bootstraped in the project root folder once Sagui is first installed. At its simplest it could be just:\n\n```js\n// sagui.config.js\nmodule.exports = {\n  pages: ['index']\n}\n```\n\nThen we can add extra configuration on top of it:\n\n### `pages`\n\nThese are static **applications** that can be built around multiple pages. Each page is the combination of an `html` and a `js` file.\n\n```js\n// sagui.config.js\nmodule.exports = {\n  pages: ['index', 'about']\n}\n```\n\nThe previous configuration will expect and build the files:\n\n- `src/about.html` =\u003e `dist/about.html`\n- `src/about.js` =\u003e `dist/about.js`\n- `src/index.html` =\u003e `dist/index.html`\n- `src/index.js` =\u003e `dist/index.js`\n\n#### Excluding a page from chunks\n\nIf you want a page to be excluded from either the [vendor](#chunksvendor) or [common](#chunkscommon) chunk, then you can do so by providing an object with a `name` and `independent` flag (set to `true`) instead of just the name of the page.\n\n```js\n// sagui.config.js\nmodule.exports = {\n  pages: ['index', 'about', { name: 'demo', independent: true }]\n}\n```\n\n### `chunks.vendor`\n\nIf you want all your external dependencies (`node_modules`) in your [pages](#pages) to be bundled together in a \"vendor\" chunk, then set this flag to `true`. By default it is set to `false`.\n\n```js\n// sagui.config.js\nmodule.exports = {\n  chunks: {\n    vendor: true\n  }\n}\n```\n\n### `chunks.common`\n\nIf you do not want all the common dependencies of your [pages](#pages) to be bundled together in a \"common\" chunk, then set this flag to `false`. By default it is set to `true`.\n\n```js\n// sagui.config.js\nmodule.exports = {\n  chunks: {\n    common: false\n  }\n}\n```\n\n### `libraries`\n\nCreate **reusable libraries** that can be shared across applications. Sagui will take care of the build process so that external libraries are not bundled and that you have a CommonJS module as the output.\n\nIt works similarly to *pages*, allowing a list of \"library entry points\" to be built. The only difference here is that each library points to a single JavaScript file. Taking the example of a UI toolkit project, it could have the following libraries:\n\n```js\n// sagui.config.js\nmodule.exports = {\n  libraries: ['button', 'field', 'select']\n}\n```\n\nAnd these will build the files:\n\n- `src/button.js` =\u003e `dist/button.js`\n- `src/field.js` =\u003e `dist/field.js`\n- `src/select.js` =\u003e `dist/select.js`\n\nRegarding **external dependencies**, Sagui will use the **peerDependencies** information in the project's `package.json` to determine what are the external dependencies of the library that shouldn't be bundled in the final build.\n\nAs an example, given a project with the `package.json`:\n\n```json\n{\n  \"name\": \"library-project\",\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"left-pad\": \"1.1.0\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"^0.14.7\"\n  }\n}\n```\n\nAnd somewhere in the source there are the following imports:\n\n```js\nimport React from 'react'\nimport leftPad from 'left-pad'\n```\n\nWhen building the project, `react` won't actually be bundled in the output but `left-pad` will, so your project won't blow up once `left-pad` is unpublished again.\n\n#### Publishing libraries as UMD\n\nIf you need to build your library targeting UMD, you can use a slightly different configuration. For UMD you need to provide a _umdName_ for the library, which is going to be the name that it will use to add itself to the `window` object when loaded as a global in the browser.\n\n```js\n// sagui.config.js\nmodule.exports = {\n  libraries: [\n    {\n      main: 'button',\n      umdName: 'MyUIButton'\n    }\n  ]\n}\n```\n\n### `browsers`\n\nList of browsers using the [browserslist format](https://github.com/ai/browserslist) that the target build must support.\n\n```js\n// sagui.config.js\nmodule.exports = {\n  browsers: [\n    '\u003e 1%',\n    'last 2 versions',\n    'IE 10'\n  ]\n}\n```\n\nIf not provided, the above default will be used instead.\n\nThis information is used to decide:\n\n- JavaScript language features to transpile;\n- CSS prefixes to append.\n\nInternally Sagui uses [babel-preset-env](https://github.com/babel/babel-preset-env) and [autoprefixer](https://github.com/postcss/autoprefixer).\n\n### `style.cssModules`\n\nBy default, styles compiled with Sagui will be output as [CSS Modules](https://github.com/css-modules), meaning they won't be global.\n\nIt is possible to disable this behavior and have regular CSS styles:\n\n```js\n// sagui.config.js\nmodule.exports = {\n  style: {\n    cssModules: false\n  }\n}\n```\n\n### `style.sourceMaps`\n\nSource maps are never generated for styles, but it is possible to enable it.\n\n```js\n// sagui.config.js\nmodule.exports = {\n  style: {\n    sourceMaps: true\n  }\n}\n```\n\n### `style.extract`\n\nBy default, when building **pages**, Sagui [extracts](https://github.com/webpack/extract-text-webpack-plugin) the CSS definitions into separated `.css` files. It is possible to disable this behavior and have the CSS inlined in the same JavaScript bundle.\n\n```js\n// sagui.config.js\nmodule.exports = {\n  style: {\n    extract: false\n  }\n}\n```\n\n### `javaScript.transpileDependencies`\n\nDependencies **installed through npm** are not transpiled with Babel by default. If you have a dependency that needs to be transpiled it is very easy, just add its name to the list:\n\n```js\n// sagui.config.js\nmodule.exports = {\n  javaScript: {\n    transpileDependencies: ['dependency-to-be-transpiled']\n  }\n}\n```\n\n### `javaScript.typeCheckAll`\n\nBy default, Flowtype ignores files that don't start with the `// @flow` comment line. If you want all your files to be statically type checked, you can enable that feature in the sagui config:\n\n```js\n// sagui.config.js\nmodule.exports = {\n  javaScript: {\n    typeCheckAll: true\n  }\n}\n```\n\n### `develop.proxy`\n\nAllow proxying requests to a separate, possible external, backend server.\n\n```js\n// sagui.config.js\nmodule.exports = {\n  develop: {\n    proxy: {\n      '/some/path*': {\n        target: 'https://other-server.example.com',\n        secure: false\n      }\n    }\n  }\n}\n```\n\nPlease check [node-http-proxy documentation](https://github.com/nodejitsu/node-http-proxy#options) for the available configuration options.\n\n## Escape hatches\n\nIf a build requirement can't be achieved via the previous configuration options, first [open an issue](https://github.com/saguijs/sagui/issues) so that we can add official support, and if you can't wait or is something very specific to your project, there is an **escape hatch** to allow extending the internal configurations.\n\n**These options are for advanced users that are familiar with how Webpack and Karma work.**\n\n### `disableLoaders`\n\nDisable internal Sagui Webpack loaders in order to implement custom behavior via the `additionalWebpackConfig`.\n\n```js\n// sagui.config.js\nmodule.exports = {\n  disableLoaders: ['yaml']\n}\n```\n\nPossible values:\n\n- `font`\n- `html`\n- `image`\n- `javaScript`\n- `style`\n- `txt`\n- `video`\n- `yaml`\n\n\n### `additionalWebpackConfig`\n\nExtend the internal Webpack configuration using [webpack-merge](https://github.com/survivejs/webpack-merge).\n\nFor example, It is possible to add additional Webpack plugins, like [git-revision-webpack-plugin](https://github.com/pirelenito/git-revision-webpack-plugin) by:\n\n```js\n// sagui.config.js\nvar GitRevisionPlugin = require('git-revision-webpack-plugin')\n\nmodule.exports = {\n  additionalWebpackConfig: {\n    plugins: [\n      new GitRevisionPlugin()\n    ]\n  }\n}\n```\n\nFor more information about configuring Webpack, check the [Webpack documentation](https://webpack.js.org/configuration/).\n\n### `additionalKarmaConfig`\n\nExtend the internal Karma configuration.\n\nAs an example, let's change the default browser used to execute the tests from *PhantomJS* to *Chrome*. In the `sagui.config.js` file:\n\n```js\n// sagui.config.js\nmodule.exports = {\n  additionalKarmaConfig: {\n    browsers: ['Chrome']\n  }\n}\n```\n\nFor more information about configuring Karma, check the [Karma documentation](https://karma-runner.github.io/1.0/config/configuration-file.html).\n\n## Gotchas\n\n### `Invalid Host header` - Accessing dev server from outside `localhost`\n\nBy default, Webpack disables access to the development server for hosts other than `localhost`, which means the development server will not be accessible from outside. If you want to give external access to the development server, you can set the `develop.disableHostCheck` to `true`:\n\n```js\n// sagui.config.js\nmodule.exports = {\n  develop: {\n    disableHostCheck: true\n  }\n}\n```\n\n### React Router\n\nFor [`react-router`](https://github.com/ReactTraining/react-router) to work on the development server, an absolute static path for the output has to be configured on Webpack. You can do that by adding this configuration to `sagui.config.js`:\n\n```js\n// sagui.config.js\nmodule.exports = {\n  additionalWebpackConfig: {\n    output: {\n      publicPath: '/'\n    }\n  }\n}\n```\n\n## Logo\n\n[Monkey artwork](https://thenounproject.com/term/monkey/267835) created by Ryan Spiering from the Noun Project.\n\n## Contributing and development\n\nTo develop the tool locally, we will need to resort to a combination of a global [npm link](https://docs.npmjs.com/cli/link) and local links in projects.\n\nYou can start by linking Sagui globally. While at its folder:\n\n```bash\nnpm link\n```\n\nThe environment variable is to inform Sagui that it is working in a \"linked environment\".\n\nThen, **in the project you intend to use Sagui**, link it locally:\n\n```bash\nnpm link sagui\n```\n\nNow, the project is set to use your development copy of Sagui. Unfortunately, you will need to run any command in the project providing the environment variable `SAGUI_LINK`:\n\n```bash\nSAGUI_LINK=true npm start\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaguijs%2Fsagui","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsaguijs%2Fsagui","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaguijs%2Fsagui/lists"}