github

saguijs / sagui

  • суббота, 2 июля 2016 г. в 03:13:11
https://github.com/saguijs/sagui

JavaScript
🐒 Front-end tooling in a single dependency



Sagui

Build Status npm version js-standard-style

Sagui is the single development dependency that provides the tooling required to build, test and develop modern JavaScript applications.

Its main goal is to kill the need of global CLIs and boilerplates, making a reproducible and easily updated environment across projects.

It follows an opinionated convention over configuration approach, providing a solid foundation so that you can focus on writing your code and not your tooling.

Quick start in 3 steps!

Let's create a new front-end project from scratch.

In a new folder, create a new npm project:

npm init -y

Install Sagui locally as a development dependency:

npm install --save-dev sagui

Start the development server:

npm start

Done! Sagui is an auto-bootstraping library, so during the install process (in a fresh npm project) it automatically creates a basic project scaffolding:

├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .gitignore
├── node_modules
│   └── sagui
├── package.json
├── sagui.config.js
└── src
    ├── index.html
    ├── index.js
    ├── index.css
    └── index.spec.js

Just start writing the code inside the src/ folder.

npm scripts

Sagui manages the package.json scripts for you:

  • npm run build: build a development version of the project;
  • npm run develop: spin up a development server with live-reload and HMR;
  • npm run dist: build a production ready version of the project;
  • npm run start: alias for the develop script;
  • npm run test: run all test related scripts below;
  • npm run test:lint: run static analysis in the code;
  • npm run test:unit: run the unit tests;
  • npm run test:coverage: run the unit tests with coverage report;
  • npm run test:unit:watch: run a test watcher (great for development).

Features

As stated earlier, Sagui strives to provide all the basic needs to create modern JavaScript applications.

Development server

The development server out-of-the-box has live reloading and hot-module replacement.

ReactJS has first-class support via react-transform, so updating components' source reflects instantly (without full refresh) in the browser.

Build

Sagui uses Webpack 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:

  • Fonts (.woff, .woff2, .ttf, .eot)
  • Images (.png, .jpg, .jpeg, .gif, .svg)
  • JavaScript (.js, .es6, .jsx) via Babel
  • JSON
  • Styles in CSS Modules in either plain CSS or Sass lang
  • Video (.ogg, .mp4)
  • YAML

During build, optimizations and special processing are also performed in the output bundle:

Testing and quality

Test automation in Sagui is achieved by creating .spec.js files inside the src/ folder using the Jasmine framework.

A simple example would be:

  • src/components/button.js
  • src/components/button.spec.js

Sagui will automatically run every test file that follows this convention.

Under the hood it uses Karma test runner to allow running the tests in the most diverse browsers and even through Selenium (not natively).

Static code analysis is also performed on the code following the JavaScript Standard Style convention.

Configuration

The 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:

module.exports = {
  pages: ['index']
}

Then we can add extra configuration on top of it:

pages

These are static applications that can be built around multiple pages. Each page is the combination of an html and a js file.

module.exports = {
  pages: ['index', 'about']
}

The previous configuration will expect and build the files:

  • src/about.html => dist/about.html
  • src/about.js => dist/about.js
  • src/index.html => dist/index.html
  • src/index.js => dist/index.js

library

Create 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.

It 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:

module.exports = {
  libraries: ['button', 'field', 'select']
}

And these will build the files:

  • src/button.js => dist/button.js
  • src/field.js => dist/field.js
  • src/select.js => dist/select.js

Regarding 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.

As an example, given a project with the package.json:

{
  "name": "library-project",
  "version": "1.0.0",
  "main": "index.js",
  "dependencies": {
    "left-pad": "1.1.0"
  },
  "peerDependencies": {
    "react": "^0.14.7"
  }
}

And somewhere in the source there are the following imports:

import React from 'react'
import leftPad from 'left-pad'

When 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.

style.cssModules

By default, styles compiled with Sagui will be output as CSS Modules, meaning they won't be global.

It is possible to disable this behavior and have regular CSS styles:

module.exports = {
  style: {
    cssModules: false
  }
}

javaScript.transpileDependencies

Dependencies 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:

module.exports = {
  javaScript: {
    transpileDependencies: ['dependency-to-be-transpiled']
  }
}

webpack

If a build requirement can't be achieved via the previous configuration options, an escape hatch is offered allowing extension of the internal Webpack configuration.

As an example, let's add an extra loader to load HTML files. In the sagui.config.js file:

module.exports = {
  webpack: {
    module: {
      loaders: [{
        test: /\.html$/,
        loader: 'html'
      }]
    }
  }
}

For more information about configuring Webpack, check the Webpack documentation.

For more information on how the merging of Webpack configurations work, check webpack-merge.

disabledLoaders

Disable internal Sagui loaders in order to implement custom behavior via the webpack configuration.

module.exports = {
  disabledLoaders: ['yaml']
}

Possible values:

  • font
  • image
  • javaScript
  • json
  • style
  • video
  • yaml

karma

If a test automation requirement can't be achieved via the previous configuration options, an escape hatch is offered allowing extension of the internal Karma configuration.

As an example, let's change the default browser used to execute the tests from PhantomJS to Chrome. In the sagui.config.js file:

module.exports = {
  karma: {
    browsers: ['Chrome']
  }
}

For more information about configuring Karma, check the Karma documentation.

Logo

Monkey artwork created by Ryan Spiering from the Noun Project.

Contributing and development

To develop the tool locally, we will need to resort to a combination of a global npm link and local links in projects.

You can start by linking Sagui globally. While at its folder:

npm link

The environment variable is to inform Sagui that it is working in a "linked environment".

Then, in the project you intend to use Sagui, link it locally:

npm link sagui

Now, 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:

SAGUI_LINK=true npm start