# Introduction

![Elixir Logo](https://3625461587-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LA-UVvDWU72L1kpFjM1%2F-LJWie_Qn6tCIUqZZ6cm%2F-LJWif80Q-EAPMybLJoR%2FelixirLogo300.png?generation=1533869209077200\&alt=media)

ColdBox Elixir provides a clean, fluent API for defining basic [Webpack](http://webpack.js.org/) tasks for your ColdBox applications.

## Versioning

ColdBox Elixir is maintained under the [Semantic Versioning](http://semver.org) guidelines as much as possible. Releases will be numbered with the following format:

```
<major>.<minor>.<patch>
```

And constructed with the following guidelines:

* Breaking backward compatibility bumps the major (and resets the minor and patch)
* New additions without breaking backward compatibility bumps the minor (and resets the patch)
* Bug fixes and misc changes bumps the patch

## License

MIT License: <https://opensource.org/licenses/MIT>.

## Important Links

* Code: <http://github.com/ortus-solutions/coldbox-elixir>
* Issues: <https://ortussolutions.atlassian.net/secure/RapidBoard.jspa?projectKey=ELIXIR>
* Documentation: <http://coldbox-elixir.ortusbooks.com>

## Discussion & Help

The Box products help and discussion group can be found here: <https://community.ortussolutions.com/>

## Professional Open Source

![Ortus Solutions, Corp](https://3625461587-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LA-UVvDWU72L1kpFjM1%2F-LA-UcAbzQgI5k76CBWv%2F-LA-Urlw3YTQ0MOv_m1a%2Fortussolutions_button.png?generation=1523648005546902\&alt=media)

ColdBox Elixir is a professional open source software backed by [Ortus Solutions, Corp](http://www.ortussolutions.com/services) offering services like:

* Custom Development
* Professional Support & Mentoring
* Training
* Server Tuning
* Security Hardening
* Code Reviews
* [Much More](http://www.ortussolutions.com/services)

### HONOR GOES TO GOD ABOVE ALL

Because of His grace, this project exists. If you don't like this, then don't read it, it's not for you.

> "Therefore being justified by **faith**, we have peace with God through our Lord Jesus Christ: By whom also we have access by **faith** into this **grace** wherein we stand, and rejoice in hope of the glory of God." Romans 5:5


# Changelog

## 4.0.0

No API changes, but lots of dependency changes.  You'll want to remove all `node_modules` so Elixir can install the needed dependencies and version.

* Node 16+&#x20;
* Webpack 5
* Node Sass has been removed in favor of Dart Sass
  * Removes Python dependency
  * Removes usages of node-gyp
* Supports Vue 2 and Vue 3

After the installation, you may notice old Webpack plugins that are no longer needed as of Webpack 5.  You may safely remove these.

You will need to tweak your `package.json` scripts to account for Webpack 5:

```json
{
    "scripts": {
        "dev": "webpack --node-env development",
        "watch": "npm run dev -- --watch",
        "prod": "webpack --node-env production"
    }
}
```

Lastly, we've introduced a new `enableDevtools` flag that can be used to force devtools in production environments:

```javascript
const elixir = require("coldbox-elixir");

elixir.enableDevtools = true;

module.exports = elixir(mix => {
    // ...
});
```

You do not need to do this for non-production environments.  The devtools will be enabled automatically there.

## 3.0.0

* **Major upgrade** to ColdBox Elixir.  No longer mirroring Laravel Elixir.
* All compilation is done through Webpack instead of Gulp.
* Removed the following methods:
  * `mix.less`
  * `mix.stylus`,
  * `mix.scripts`
  * `mix.scriptsIn`
  * `mix.webpack`
  * `mix.browserify`,
  * `mix.rollup`
  * `mix.version`
  * `mix.exec`
  * `mix.task`
* The entire Elixir configuration object has changed.  See [Configuration Options](/configuration_options) for details.
* PostCSS support is now automatic if a `postcss.config.js` file is found in the project root.
* The `elixir` and `elixirPath` helper functions in ColdBox 5.0.0 and earlier are incompatible with ColdBox Elixir 3.0.0.  Please see the [Versioning docs](/versioning) for updated helper functions.

## 2.0.0

* Updated to stay current with Laravel Elixir 6.0.0.
* Deprecated `mix.babel()` in favor of `mix.browserify()`, `mix.webpack`, `mix.rollup`, or similar module bundlers.
* Nicer console output.
* Broke out first party extensions from the core (to keep in line with Laravel Elixir 6.0.0)
  * [`coldbox-elixir-browserify`](https://github.com/coldbox-elixir/extension-browserify)
  * [`coldbox-elixir-browsersync`](https://github.com/coldbox-elixir/extension-browsersync)
  * [`coldbox-elixir-rollup`](https://github.com/coldbox-elixir/extension-rollup)
  * [`coldbox-elixir-stylus`](https://github.com/coldbox-elixir/extension-stylus)
  * [`coldbox-elixir-vue`](https://github.com/coldbox-elixir/extension-vue)
  * [`coldbox-elixir-webpack`](https://github.com/coldbox-elixir/extension-webpack)
* Helpful warnings when trying to use methods provided by a first party extension.

## 1.1.0

* Travis Support
* BDD via TestBox fixes
* Updated all dependencies to latest versions
* Gulp tasks for compilation, tests and watchers
* Test App additions for testing direct gulp integrations
* If not tasks defined in the user's gulpfile, just a message is shown instead of an exception
* Removed coffeescript support, no longer needed
* Added new config map for `appPaths` to support all ColdBox conventions
* Vueify core support view browserify for Vue.js components
* Included a new `template` folder which helps setting up new elixir based projects

## 1.0.0

* Initial Port to ColdBox


# Migration Guide

## v4.0.0

No API changes, but lots of dependency changes.  You'll want to remove all `node_modules` so Elixir can install the needed dependencies and version.

* Node 16+&#x20;
* Webpack 5
* Node Sass has been removed in favor of Dart Sass
  * Removes Python dependency
  * Removes usages of node-gyp
* Supports Vue 2 and Vue 3

After the installation, you may notice old Webpack plugins that are no longer needed as of Webpack 5.  You may safely remove these.

You will need to tweak your `package.json` scripts to account for Webpack 5:

```json
{
    "scripts": {
        "dev": "webpack --node-env development",
        "watch": "npm run dev -- --watch",
        "prod": "webpack --node-env production"
    }
}
```

Lastly, we've introduced a new `enableDevtools` flag that can be used to force devtools in production environments:

```javascript
const elixir = require("coldbox-elixir");

elixir.enableDevtools = true;

module.exports = elixir(mix => {
    // ...
});
```

You do not need to do this for non-production environments.  The devtools will be enabled automatically there.

## v3.0.0

If you used a previous version of ColdBox Elixir a lot has changed. This guide will step you through the changes.

## Dependencies

ColdBox Elixir no longer requires `gulp`. You can uninstall it.

ColdBox Elixir will install all necessary dependencies when installing or updating it from NPM. There are other dependencies which may be installed on-demand once as you use them.

## Running Elixir

Since ColdBox Elixir doesn't use `gulp` any more, we need to make some changes to our `gulpfile.js`.

1. Rename `gulpfile.js` to `webpack.config.js`.
2. Export the result of `elixir()`

```javascript
// webpack.config.js
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    // ....
});
```

1. (Optional) Create some NPM scripts to make build commands easier to remember. This let's us run `npm run dev` or `npm run watch` to build our project.

```javascript
{
    "scripts": {
        "dev": "webpack",
        "watch": "npm run dev -- --watch",
        "build": "npm run dev -- -p"
    }
}
```

## Asset Names

Due to the way Webpack processes css files, you can no longer have a css file named `vendor`.

## Tasks

The following tasks have been removed from ColdBox Elixir.

* `mix.less`
* `mix.combine`
* `mix.browserify`
* `mix.rollup`
* `mix.exec`

If you rely on any of these methods you can either stay with ColdBox Elixir v2 or you can [recreate the task yourself.](/writing_elixir_extensions)

## Method Changes

### `mix.styles`

`mix.styles` should be replaced with `mix.css`.

The method signature for `mix.css` is has changed.

| Name                    | Type   | Required | Default                                        | Description                                                                      |
| ----------------------- | ------ | -------- | ---------------------------------------------- | -------------------------------------------------------------------------------- |
| filename                | String | `true`   |                                                | The filename to bundle.                                                          |
| options                 | Object | `false`  | (see below)                                    | An object for additional options. Any missing keys will use their default value. |
| options.name            | String | `false`  | The name of the filename without the extension | The name of the outputed bundle                                                  |
| options.outputDirectory | String | `false`  | `includes/css`                                 | The output directory for the built file.                                         |
| options.entryDirectory  | String | `false`  | `resources/assets/css/`                        | The directory where the filename is located.                                     |

### `mix.scripts`

`mix.scripts` should be replaced with [`mix.js`](/working_with_scripts). `mix.js` will automatically run the code through Babel. Babel is preconfigured with `babel-preset-env`, but it can be customized by specifying your own `.babelrc` file in the root of your project. See the [Babel docs](https://babeljs.io/docs/en/babelrc) for more information.

The method signature for `mix.scripts` has changed.

| Name                    | Type   | Required | Default                                        | Description                                                                      |
| ----------------------- | ------ | -------- | ---------------------------------------------- | -------------------------------------------------------------------------------- |
| filename                | String | `true`   |                                                | The filename to bundle.                                                          |
| options                 | Object | `false`  | (see below)                                    | An object for additional options. Any missing keys will use their default value. |
| options.name            | String | `false`  | The name of the filename without the extension | The name of the outputed bundle                                                  |
| options.outputDirectory | String | `false`  | `includes/js`                                  | The output directory for the built file.                                         |
| options.entryDirectory  | String | `false`  | `resources/assets/js/`                         | The directory where the filename is located.                                     |

### `mix.webpack`

`mix.webpack` should be replaced with either [`mix.js`](/working_with_scripts) or [`mix.vue`](/vuejs_integration) depending on your use case. `mix.vue` includes some extra dependencies and configuration to process `.vue` files while `mix.js` will just process your files through Babel.

The method signature for `mix.js` and `mix.vue` are the same.

| Name                    | Type   | Required | Default                                        | Description                                                                      |
| ----------------------- | ------ | -------- | ---------------------------------------------- | -------------------------------------------------------------------------------- |
| filename                | String | `true`   |                                                | The filename to bundle.                                                          |
| options                 | Object | `false`  | (see below)                                    | An object for additional options. Any missing keys will use their default value. |
| options.name            | String | `false`  | The name of the filename without the extension | The name of the outputed bundle                                                  |
| options.outputDirectory | String | `false`  | `includes/js`                                  | The output directory for the built file.                                         |
| options.entryDirectory  | String | `false`  | `resources/assets/js/`                         | The directory where the filename is located.                                     |

### `mix.sass`

The method signature for `mix.sass` has changed.

| Name                    | Type   | Required | Default                                        | Description                                                                      |
| ----------------------- | ------ | -------- | ---------------------------------------------- | -------------------------------------------------------------------------------- |
| filename                | String | `true`   |                                                | The filename to bundle.                                                          |
| options                 | Object | `false`  | (see below)                                    | An object for additional options. Any missing keys will use their default value. |
| options.name            | String | `false`  | The name of the filename without the extension | The name of the outputed bundle                                                  |
| options.outputDirectory | String | `false`  | `includes/css`                                 | The output directory for the built file.                                         |
| options.entryDirectory  | String | `false`  | `resources/assets/sass/`                       | The directory where the filename is located.                                     |

### `mix.version`

Versioning is now the default for a production build (`webpack -p`). You can also control if the files are versioned by setting the `elixir.versioning` config property in your `webpack.config.js` file.

### `mix.stylesIn` and `mix.scriptsIn`

These methods should be replaced with individual calls to `mix.css` and `mix.js`.

## Extensions

Extensions that were made for ColdBox Elixir v2 are not compatible with v3. See [*Writing Elixir Extensions*](/writing_elixir_extensions) for more information on how to create v3 compatible extensions.

## Elixir Config File

The Elixir config file has changed completely. The available configuration options are available in [*Configuration Options.*](/configuration_options)


# Installation

## Installing Node

Before triggering Elixir, you must first ensure that [Node.js](https://nodejs.org/en/) is installed on your machine. You will want at least the latest LTS version of Node.

```
node -v
```

## Installing ColdBox Elixir

If you generate a ColdBox application using any of our [elixir templates](https://github.com/coldbox-templates/) then you will find a `package.json` file in the root of the application already. Think of this like your `box.json` file, except it defines Node dependencies instead of ColdFusion (CFML) dependencies. A typical example can look like this:

```javascript
{
  "private": true,
  "devDependencies": {
    "coldbox-elixir": "^4.0.0"
  }
}
```

It defines ColdBox Elixir as a dev dependency. You may then install the dependencies it references by running:

```
npm install
```

This will install ColdBox Elixir and its dependencies into the `node_modules` folder in your root. This folder has been already added to the `.gitignore` file as well, so no need to further ignore it.


# Running Elixir

Elixir is built on top of Webpack, so to run your Elixir tasks you only need to run the `webpack` command in your terminal. Before running Webpack, you will need a `webpack.config.js` file in the root of your project. Below is a simple example:

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.js("app.js");
});
```

Please note that by adding the `-p` flag to the command will turn on Webpack's production mode. This will minify your CSS and JavaScript files as well as add long-term caching hashes to your compiled files.

## Watching Assets For Changes

For performance and convienence, you can run Webpack in watch mode by passing the `-w` or `--watch` flag. Any changes to your source files will automatically re-run your build. Note that your build will be significantly faster on subsequent changes than when running Webpack from scratch.

## NPM Scripts

The easiest way to run Webpack is to set up some NPM scripts. Here are the following we recommend:

```javascript
"scripts": {
    "dev": "webpack --hide-modules",
    "watch": "npm run dev -- --watch",
    "prod": "npm run dev -- -p"
}
```

Then from the terminal you can run `npm run [scriptName for this example either dev, watch or prod]` to run the associated script.


# Configuration Options

All of Elixir's configuration is to support Webpack. Most of the custom changes you will make to Elixir will come through the `mergeConfig` method.

```javascript
const elixir = require("coldbox-elixir");

elixir.config.mergeConfig({});
```

The `mergeConfig` method will intelligently merge your new config with the existing Webpack config (thanks to [`webpack-merge`](https://github.com/survivejs/webpack-merge)).

There are a few additional config options on the Elixir object.

* `elixir.isProduction`
  * By default checks for the production flag from the terminal (`-p`)
* `elixir.rootPath`
  * The root of the project
* `elixir.config`
  * A configured instance of `ElixirConfig`
* `elixir.versioning`
  * Defaults to `elixir.isProduction`
* `elixir.base64SourceSize`
  * Defaults to 0. When configured as a number of bytes, any assets referenced in the CSS files you compile will be inlined as Base64 objects in your compiled output.  ( e.g. 1000000 = 1000kb )


# Working With Stylesheets

## Working With Stylesheets

Elixir processes all CSS files through Webpack. This brings with it some nifty Webpack properties such as [automatic url resolution](https://github.com/webpack-contrib/css-loader).

## CSS

> Due to the way Webpack processes css files, you can no longer have a css file named `vendor`.

You can mix traditional css with webpack using `mix.css`. You can pass one file or an array of files.

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.css("app.css");
    mix.css([
        "node_modules/normalizecss/normalize.css"
        "resources/assets/css/normalize_overrides.css"
    ], {
        name: "normalize.css",
        entryDirectory: ""
    });
});
```

`mix.css` accepts a configuration object as the second parameter:

```javascript
{
    name: this.withoutExtension(filename),
    outputDirectory: "includes/css/",
    entryDirectory: "resources/assets/css/"
}
```

## PostCSS

If you add a `postcss.config.js` file to the root of your project, Elixir will process all of your styles through PostCSS. To learn more about PostCSS, visit [their documentation](https://postcss.org/).

## Sass

The `sass` method allows you to compile [Sass](http://sass-lang.com/) into CSS. Assuming your Sass files are stored at `resources/assets/sass`, you may use the method like so:

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.sass("app.scss");
});
```

Like the `css` method you may compile multiple Sass files into a single CSS file, and even customize the output directory of the resulting CSS:

```
elixir( function( mix ){
    mix.sass([
        "app.scss",
        "controllers.scss"
    ], {
        outputDirectory: "public/assets/css"
    });
} );
```

## Other Pre-processors

Elixir can be extended with any other pre-processor you would like. See our docs on [writing your own extensions](/writing_elixir_extensions) for others!


# Working With Scripts

You can compile scripts using the `mix.js` method. It accepts either a single file or an array of files to combine. Each file will be crawled for dependencies by Webpack.

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.js("app.js");
    mix.js([
        "node_modules/jquery/dist/jquery.min.js",
        "node_modules/bootstrap-sass/assets/javascripts/bootstrap.min.js"
    ], {
        name: "bootstrap",
        entryDirectory: ""
    });
});
```

The second argument to `mix.js` is a configuration object.

```javascript
{
    name: this.withoutExtension(filename),
    outputDirectory: "includes/js/",
    entryDirectory: "resources/assets/js/"
}
```

## `runtime.js` and `vendor.js`

Using `mix.js` or any methods that depend on it create up to two additional files that you should be aware of: `runtime.js` and `vendor.js`. `runtime.js` is the Webpack runtime and should be included as the first script on your page. Without this script, your other files will fail silently. The `vendor.js` is comprised of any dependencies pulled from `node_modules`. This allows your users to keep using the cached `vendor.js` file even when you change your application code. This file should be included after `runtime.js` and before any of your application code.


# Versioning Cache Busting

By default, Elixir will version all your compiled assets when compiling for production `webpack -p`.

This produces a file with a unique hash in the filename. This hash will only change if the contents of the file change.

You can change or turn off the versioning by setting the `elixir.versioning` property in your `webpack.config.js` file.

Additionally, Elixir will generate an `/includes/manifest.json` file. This file maps the original file name to the hashed file name. This lets you still use the original file name in your code and not have to update your templates whenever your assets change.

ColdBox (5.1+) ships with some helper methods for this purpose. You can also copy the code below for use in your own projects.

```javascript
<cfscript>
    /**
    * Adds the versioned path for an asset to the view
    * @filename The asset path to find relative to the includes convention directory
    * @buildDirectory The build directory inside the includes convention directory
    * @sendToHeader Send to the header via htmlhead by default, else it returns the content
    * @async HTML5 JavaScript argument: Specifies that the script is executed asynchronously (only for external scripts)
    * @defer HTML5 JavaScript argument: Specifies that the script is executed when the page has finished parsing (only for external scripts)
    */
    function elixir(
        required filename,
        boolean sendToHeader=true,
        boolean async=false,
        boolean defer=false
    ){
        html.addAsset(
            elixirPath( arguments.fileName ),
            arguments.sendToHeader,
            arguments.async,
            arguments.defer
        );

        return this;
    }

    /**
    * Finds the versioned path for an asset if leveraging ColdBox Elixir
    * @returns The path
    */
    string function elixirPath( required string fileName ){
        var includesConvention     = "includes";
        var mapping             = event.getCurrentModule() != "" ? event.getModuleRoot() : controller.getSetting( "appMapping" );
        var filePath             = expandPath( "#mapping#/#includesConvention#/manifest.json" );
        var href                 = "#mapping#/#includesConvention#/#arguments.fileName#";

        if ( ! fileExists( filePath ) ) {
            return href;
        }

        var fileContents = fileRead( filePath );
        if ( ! isJSON( fileContents ) ) {
            return href;
        }

        var json = deserializeJSON( fileContents );
        if ( ! structKeyExists( json, arguments.fileName ) ) {
            return href;
        }

        return "#mapping#/#includesConvention#/#json[ arguments.fileName ]#";
    }
</cfscript>
```

You can then just use them in your layouts or views to include versioned files:

```markup
<head>
    #elixir( "css/myapp.css" )#
</head>
<body>
    <!-- ... -->

    <script src="#elixirPath( "js/app.js" )#"></script>
</body>
```


# Mixing in tasks from ColdBox Modules

ColdBox Modules can be an excellent way to structure your project, and ColdBox Elixir is the perfect companion. Use all the Elixir methods you know and love in your modules, and Elixir will build them all for you with just one command.

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.modules();
});
```

## `elixir-module.js`

To specify what Elixir functions to run a module needs to define an `elixir-module.js` file. This file looks very similar to your `webpack.config.js`. Here is an example of one:

```javascript
module.exports = mix => {
    mix.sass("app.scss");
};
```

The function here is exactly the same function you would write inside the `elixir` call in your main `webpack.config.js` file. Every method installed in your main `webpack.config.js` file is available here.

Elixir will scope the changes to the current module's directory. This means, for example, that:

```javascript
mix.sass("app.scss");
```

Inside of a module with a path `/modules_app/my-module/elixir-module.js` will look for an `app.scss` file inside of `/modules_app/my-module/resources/assets/sass/app.scss` and compile it to `/modules_app/my-module/includes/css/app.css`.

### Includes, Excludes, and File name

You can specify and array of folders to include, folders to exclude, or change the default file name if you wish:

| Argument   | Default Value      |
| ---------- | ------------------ |
| `includes` | `["modules_app"]`  |
| `excludes` | `[]`               |
| `fileName` | `elixir-module.js` |

## Running a Single Module

You can compile a single module's assets by using `mix.module()` passing in the module's name:

```javascript
// /gulpfile.js
elixir(mix => {
    mix.module("my-module");
});
```

This will look for the following file: `/modules_app/my-module/elixir-module.js` and add the resulting mix function to the gulp tasks. If the file does not exist or is not a function, Elixir will show an error and continue on with the other build tasks.

The second parameter is a configuration object to change the folderName or fileName to look for:

```javascript
elixir(mix => {
    mix.module("my-module", {
        folderName: "new_base_directory",
        fileName: "new-filename.js"
    });
});
```

This would look in `/new_base_directory/my-module/new-filename.js` for the mix function.

## Module alias

If you want use alias for your import in a module, you must use:

```javascript
import store from '@moduleName/store.js'
```


# ContentBox Integration

ColdBox Elixir has a few helper methods when working in a ContentBox app.

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.themes();
    mix.contentbox();
});
```

These two methods work just like a call to `mix.modules` with some different defaults set.

> For a refresher on how `mix.modules` and `elixir-module.js` files work, see the [modules docs.](/coldbox_modules)

## `mix.themes`

This method will look inside the `modules_app/contentbox-custom/_themes` directory for any folders with a `elixir-theme.js` file. The `elixir-theme.js` file is identical to a `elixir-module.js` file.

## `mix.contentbox`

This method will look inside the `modules_app/contentbox-custom/_modules` directory for any folders with a `elixir-module.js` file.


# Copying Files & Directories

The `copy` method may be used to copy files and/or directories to new locations. All operations are relative to the project's `root` directory:

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.copy("resources/vendor/foo/bar.css", "includes/css/bar.css");
});
```


# Deleting Files & Directories

By default the following directories are cleaned out for each build:

```
"includes/js"
"includes/css"
"includes/fonts"
"includes/media"
"includes/images"
```

If you would like to add additional directories, you can do so by configuring a new instance of the `CleanWebpackPlugin`:

```javascript
const elixir = require("coldbox-elixir");
const CleanWebpackPlugin = require("clean-webpack-plugin");

elixir.config.mergeConfig({
    plugins: [
        new CleanWebpackPlugin(["my/custom/directory"], { root: elixir.rootPath })
    ]
});
```


# Environment Variables

You will occassionally need to access environment variables in your JavaScript.  This is done using the `process.env` object like so: `process.env.YOUR_KEY_HERE`. But your user's browser won't have access to a `process` object.  How will we handle this?

### Webpack's EnvironmentPlugin

Webpack uses the [`EnvironmentPlugin`](https://webpack.js.org/plugins/environment-plugin/) to do this.  It takes an array of environment variable names to allow in your application.  Then all instances of `process.env.YOUR_KEY_HERE` will be replaced with the value in your environment.&#x20;

{% code title="Environment" %}

```bash
NODE_ENV=development
```

{% endcode %}

{% code title="webpack.config.js" %}

```javascript
module.exports = {
  // ...
  plugins: [
    // ...
    new webpack.EnvironmentPlugin(["NODE_ENV"]),
  ]
};
```

{% endcode %}

{% code title="Source File" %}

```javascript
console.log(process.env.NODE_ENV);
```

{% endcode %}

{% code title="Output File" %}

```javascript
console.log("development");
```

{% endcode %}

If the environment variable allowed is missing, an error will be thrown during compilation, ensuring that you don't accidentally ship code without this value.

In addition to passing an array of key names, you may pass an object with the keys being environment variable names and the values being default values if the keys are not found in the environment.

{% code title="webpack.config.js" %}

```javascript
module.exports = {
  // ...
  plugins: [
    // ...
    new webpack.EnvironmentPlugin({
      NODE_ENV: "development"
    }),
  ]
};
```

{% endcode %}

### mix.env

To make this process easier, Elixir has a `mix.env` method that passes through to `EnvironmentPlugin`.

{% code title="webpack.config.js" %}

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
  mix.env(["NODE_ENV"]);  
});
```

{% endcode %}

This is the easiest way to define the environment variables your JavaScript bundle needs.

### Automatic NODE\_ENV

`NODE_ENV` is a very common environment variable used by many libraries to output additional debugging information or to enable optimizations.  Since Elixir already knows what environment you are building for, this value is defaulted for you.  If you desire to override that value, just define `NODE_ENV` in your environment and it will take precendence.


# BrowserSync

[BrowserSync](https://www.browsersync.io/) automatically refreshes your web browser after you make changes to your front-end resources. You can use the `browserSync` method to instruct Elixir to start a BrowserSync server when you run the `gulp watch` command:

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.browserSync();
});
```

After running this command you will see directions to add a script tag to the bottom of your website like this:

```bash
[BS] Copy the following snippet into your website, just before the closing </body> tag
<script id="__bs_script__">//<![CDATA[
    document.write("<script async src='http://HOST:3000/browser-sync/browser-sync-client.2.12.5.js'><\/script>".replace("HOST", location.hostname));
//]]></script>
```

Add that snippet to your `layouts/Main.cfm` file and reload to enable BrowserSync!

## Specifying a Proxy

Instead of copying the script tag into you app, you can tell BrowserSync to proxy your existing CFML server:

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.browserSync({
        proxy: "localhost:50608"
    });
});
```

Running `webpack -w` will now open up `localhost:3000` which proxies to your app! No need for that BrowserSync script tag anymore!

## Default Options

We define a number of default options for BrowserSync:

```javascript
{
    host: "localhost",
    port: 3000,
    proxy: "http://localhost:8888",
    files: "**/*"
}
```

The can be overridden by passing in an options object as the only parameter (as seen above with `proxy`).

## Custom Options

In addition to the `proxy` option, you may pass any BrowserSync option here as the only argument. A list of the BrowserSync options can be found [here](http://www.browsersync.io/docs/options/).


# Vue.js Integration

ColdBox Elixir lets you work with `.vue` files out of the box.

You will begin by installing Vue.js via npm: `npm install vue`. This will add `Vue` as a dependency for your project in your project's `package.json` and into the `node_modules` directory. The following is the `package.json` you should use when integrating with Vue.js:

**package.json**

```javascript
{
  "private": true,
  "devDependencies": {
    "coldbox-elixir": "3.0.0",
  },
  "dependencies": {
    "vue": "^2.0.0"
  }
}
```

Then create your normal JavaScript and Vue components in your `resources/assets/js` folder.

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.vue("app.js");
});
```

Your `App.js` can look like this:

**resources/assets/js/App.js**

```javascript
import Vue from "vue";

new Vue({
  el: "#app",
  data: {
    message: "Hello, world!"
  }
});
```

And you can import any components following the same relative path of the `resources/assets/js` folder.

You can also use the optional `.vue` syntax which allows you to co-locate your template, styles, and scripts in a single-file component.

**resources/assets/js/App.js**

```javascript
import Vue from "vue";
import Profile from "./components/Profile.vue";

new Vue({
  el: "#app",
  components: { Profile }
});
```

**resources/assets/js/components/Profile.vue**

```
<template>
  <div class="profile">
    {{ name }}
  </div>
</template>

<script>
export default {
  data () {
    return {
      name: "Luis Majano"
    };
  }
};
</script>

<style>
.profile {
    background: #eee;
    border: 1px solid #aaa;
    border-radius: 2em;
    margin: 2em auto;
    min-height: 150px;
    padding: 2em;
    width: 300px;
}
</style>
```

You would then use this in your ColdBox layout or view like so:

```markup
<div id="app">
    <profile></profile>
</div>
<script src="/includes/js/App.js"></script>
```

Any style blocks in your `.vue` components will be extracted as well to the same directory as your javascript file as a css file. For example, if you were compiling `mix.vue( "app.js" )` Elixir would generate a `includes/js/app.css` file containing the css for the style blocks used in that entrypoint.

> Note: there are some drawbacks with style blocks in Vue components and Elixir. if you are creating multiple entry points with multiple `mix.vue` calls, any style blocks in shared components will be duplicated in each of the css files. Additionally, because Elixir is already extracting other css files, style blocks in Vue components are always extracted. For these reasons, we recommend using other approaches to managing your css with Vue components and Elixir.


# Writing Elixir Extensions

## `mergeConfig`

Occasionally you will need to extend Webpack in ways not supported by ColdBox Elixir. In these moments, you can provide your own configuration using the `mergeConfig` method.

```javascript
const elixir = require("coldbox-elixir");

elixir.config.mergeConfig({
    // custom webpack config goes here
});
```

The `mergeConfig` method will merge the object provided with the existing Webpack config using the excellent [`webpack-merge` library](https://github.com/survivejs/webpack-merge).

## Custom Ingredients

Ingredients are the name for the methods available on the `mix` object. You can add an ingredient to your Elixir instance like so:

```javascript
const elixir = require("coldbox-elixir");

elixir.config.addIngredient("nameOfIngredient", () => {
    // function to run when called (mix.nameOfIngredient());
    // any parameters passed to the `mix.nameOfIngredient()` call will be available in the function.
    // The `this` scope refers to the ElixirConfig object, so methods like `this.mergeConfig` are available.
})
```

The main use cases for using an ingredient over custom config are:

1. Need to call multiple times each time for different file(s)
2. Want to re-use across projects

Especially in the second case, feel free to publish the ingredient on NPM if you feel it could be useful to other developers.


# Introduction

![Elixir Logo](https://4036263433-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LA-UVvDWU72L1kpFjM1%2F-LJWie_Qn6tCIUqZZ6cm%2F-LJWif80Q-EAPMybLJoR%2FelixirLogo300.png?generation=1533869209077200\&alt=media)

ColdBox Elixir provides a clean, fluent API for defining basic [Webpack](http://webpack.js.org/) tasks for your ColdBox applications.

## Versioning

ColdBox Elixir is maintained under the [Semantic Versioning](http://semver.org) guidelines as much as possible. Releases will be numbered with the following format:

```
<major>.<minor>.<patch>
```

And constructed with the following guidelines:

* Breaking backward compatibility bumps the major (and resets the minor and patch)
* New additions without breaking backward compatibility bumps the minor (and resets the patch)
* Bug fixes and misc changes bumps the patch

## License

MIT License: <https://opensource.org/licenses/MIT>.

## Important Links

* Code: <http://github.com/ortus-solutions/coldbox-elixir>
* Issues: <https://ortussolutions.atlassian.net/secure/RapidBoard.jspa?projectKey=ELIXIR>
* Documentation: <http://coldbox-elixir.ortusbooks.com>

## Discussion & Help

The Box products help and discussion group can be found here: <https://community.ortussolutions.com/>

## Professional Open Source

![Ortus Solutions, Corp](https://4036263433-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LA-UVvDWU72L1kpFjM1%2F-LA-UcAbzQgI5k76CBWv%2F-LA-Urlw3YTQ0MOv_m1a%2Fortussolutions_button.png?generation=1523648005546902\&alt=media)

ColdBox Elixir is a professional open source software backed by [Ortus Solutions, Corp](http://www.ortussolutions.com/services) offering services like:

* Custom Development
* Professional Support & Mentoring
* Training
* Server Tuning
* Security Hardening
* Code Reviews
* [Much More](http://www.ortussolutions.com/services)

### HONOR GOES TO GOD ABOVE ALL

Because of His grace, this project exists. If you don't like this, then don't read it, it's not for you.

> "Therefore being justified by **faith**, we have peace with God through our Lord Jesus Christ: By whom also we have access by **faith** into this **grace** wherein we stand, and rejoice in hope of the glory of God." Romans 5:5


# Changelog

## 3.0.0

* **Major upgrade** to ColdBox Elixir.  No longer mirroring Laravel Elixir.
* All compilation is done through Webpack instead of Gulp.
* Removed the following methods:
  * `mix.less`
  * `mix.stylus`,
  * `mix.scripts`
  * `mix.scriptsIn`
  * `mix.webpack`
  * `mix.browserify`,
  * `mix.rollup`
  * `mix.version`
  * `mix.exec`
  * `mix.task`
* The entire Elixir configuration object has changed.  See [Configuration Options](/v3/configuration_options) for details.
* PostCSS support is now automatic if a `postcss.config.js` file is found in the project root.
* The `elixir` and `elixirPath` helper functions in ColdBox 5.0.0 and earlier are incompatible with ColdBox Elixir 3.0.0.  Please see the [Versioning docs](/v3/versioning) for updated helper functions.

## 2.0.0

* Updated to stay current with Laravel Elixir 6.0.0.
* Deprecated `mix.babel()` in favor of `mix.browserify()`, `mix.webpack`, `mix.rollup`, or similar module bundlers.
* Nicer console output.
* Broke out first party extensions from the core (to keep in line with Laravel Elixir 6.0.0)
  * [`coldbox-elixir-browserify`](https://github.com/coldbox-elixir/extension-browserify)
  * [`coldbox-elixir-browsersync`](https://github.com/coldbox-elixir/extension-browsersync)
  * [`coldbox-elixir-rollup`](https://github.com/coldbox-elixir/extension-rollup)
  * [`coldbox-elixir-stylus`](https://github.com/coldbox-elixir/extension-stylus)
  * [`coldbox-elixir-vue`](https://github.com/coldbox-elixir/extension-vue)
  * [`coldbox-elixir-webpack`](https://github.com/coldbox-elixir/extension-webpack)
* Helpful warnings when trying to use methods provided by a first party extension.

## 1.1.0

* Travis Support
* BDD via TestBox fixes
* Updated all dependencies to latest versions
* Gulp tasks for compilation, tests and watchers
* Test App additions for testing direct gulp integrations
* If not tasks defined in the user's gulpfile, just a message is shown instead of an exception
* Removed coffeescript support, no longer needed
* Added new config map for `appPaths` to support all ColdBox conventions
* Vueify core support view browserify for Vue.js components
* Included a new `template` folder which helps setting up new elixir based projects

## 1.0.0

* Initial Port to ColdBox


# Migration Guide

If you used a previous version of ColdBox Elixir a lot has changed. This guide will step you through the changes.

## Dependencies

ColdBox Elixir no longer requires `gulp`. You can uninstall it.

ColdBox Elixir will install all necessary dependencies when installing or updating it from NPM. There are other dependencies which may be installed on-demand once as you use them.

## Running Elixir

Since ColdBox Elixir doesn't use `gulp` any more, we need to make some changes to our `gulpfile.js`.

1. Rename `gulpfile.js` to `webpack.config.js`.
2. Export the result of `elixir()`

```javascript
// webpack.config.js
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    // ....
});
```

1. (Optional) Create some NPM scripts to make build commands easier to remember. This let's us run `npm run dev` or `npm run watch` to build our project.

```javascript
{
    "scripts": {
        "dev": "webpack",
        "watch": "npm run dev -- --watch",
        "build": "npm run dev -- -p"
    }
}
```

## Asset Names

Due to the way Webpack processes css files, you can no longer have a css file named `vendor`.

## Tasks

The following tasks have been removed from ColdBox Elixir.

* `mix.less`
* `mix.combine`
* `mix.browserify`
* `mix.rollup`
* `mix.exec`

If you rely on any of these methods you can either stay with ColdBox Elixir v2 or you can [recreate the task yourself.](/v3/writing_elixir_extensions)

## Method Changes

### `mix.styles`

`mix.styles` should be replaced with `mix.css`.

The method signature for `mix.css` is has changed.

| Name                    | Type   | Required | Default                                        | Description                                                                      |
| ----------------------- | ------ | -------- | ---------------------------------------------- | -------------------------------------------------------------------------------- |
| filename                | String | `true`   |                                                | The filename to bundle.                                                          |
| options                 | Object | `false`  | (see below)                                    | An object for additional options. Any missing keys will use their default value. |
| options.name            | String | `false`  | The name of the filename without the extension | The name of the outputed bundle                                                  |
| options.outputDirectory | String | `false`  | `includes/css`                                 | The output directory for the built file.                                         |
| options.entryDirectory  | String | `false`  | `resources/assets/css/`                        | The directory where the filename is located.                                     |

### `mix.scripts`

`mix.scripts` should be replaced with [`mix.js`](/v3/working_with_scripts). `mix.js` will automatically run the code through Babel. Babel is preconfigured with `babel-preset-env`, but it can be customized by specifying your own `.babelrc` file in the root of your project. See the [Babel docs](https://babeljs.io/docs/en/babelrc) for more information.

The method signature for `mix.scripts` has changed.

| Name                    | Type   | Required | Default                                        | Description                                                                      |
| ----------------------- | ------ | -------- | ---------------------------------------------- | -------------------------------------------------------------------------------- |
| filename                | String | `true`   |                                                | The filename to bundle.                                                          |
| options                 | Object | `false`  | (see below)                                    | An object for additional options. Any missing keys will use their default value. |
| options.name            | String | `false`  | The name of the filename without the extension | The name of the outputed bundle                                                  |
| options.outputDirectory | String | `false`  | `includes/js`                                  | The output directory for the built file.                                         |
| options.entryDirectory  | String | `false`  | `resources/assets/js/`                         | The directory where the filename is located.                                     |

### `mix.webpack`

`mix.webpack` should be replaced with either [`mix.js`](/v3/working_with_scripts) or [`mix.vue`](/v3/vuejs_integration) depending on your use case. `mix.vue` includes some extra dependencies and configuration to process `.vue` files while `mix.js` will just process your files through Babel.

The method signature for `mix.js` and `mix.vue` are the same.

| Name                    | Type   | Required | Default                                        | Description                                                                      |
| ----------------------- | ------ | -------- | ---------------------------------------------- | -------------------------------------------------------------------------------- |
| filename                | String | `true`   |                                                | The filename to bundle.                                                          |
| options                 | Object | `false`  | (see below)                                    | An object for additional options. Any missing keys will use their default value. |
| options.name            | String | `false`  | The name of the filename without the extension | The name of the outputed bundle                                                  |
| options.outputDirectory | String | `false`  | `includes/js`                                  | The output directory for the built file.                                         |
| options.entryDirectory  | String | `false`  | `resources/assets/js/`                         | The directory where the filename is located.                                     |

### `mix.sass`

The method signature for `mix.sass` has changed.

| Name                    | Type   | Required | Default                                        | Description                                                                      |
| ----------------------- | ------ | -------- | ---------------------------------------------- | -------------------------------------------------------------------------------- |
| filename                | String | `true`   |                                                | The filename to bundle.                                                          |
| options                 | Object | `false`  | (see below)                                    | An object for additional options. Any missing keys will use their default value. |
| options.name            | String | `false`  | The name of the filename without the extension | The name of the outputed bundle                                                  |
| options.outputDirectory | String | `false`  | `includes/css`                                 | The output directory for the built file.                                         |
| options.entryDirectory  | String | `false`  | `resources/assets/sass/`                       | The directory where the filename is located.                                     |

### `mix.version`

Versioning is now the default for a production build (`webpack -p`). You can also control if the files are versioned by setting the `elixir.versioning` config property in your `webpack.config.js` file.

### `mix.stylesIn` and `mix.scriptsIn`

These methods should be replaced with individual calls to `mix.css` and `mix.js`.

## Extensions

Extensions that were made for ColdBox Elixir v2 are not compatible with v3. See [*Writing Elixir Extensions*](/v3/writing_elixir_extensions) for more information on how to create v3 compatible extensions.

## Elixir Config File

The Elixir config file has changed completely. The available configuration options are available in [*Configuration Options.*](/v3/configuration_options)


# Installation

## Installing Node

Before triggering Elixir, you must first ensure that [Node.js](https://nodejs.org/en/) is installed on your machine. You will want at least the latest LTS version of Node.

```
node -v
```

## Installing ColdBox Elixir

If you generate a ColdBox application using any of our [elixir templates](https://github.com/coldbox-templates/) then you will find a `package.json` file in the root of the application already. Think of this like your `box.json` file, except it defines Node dependencies instead of ColdFusion (CFML) dependencies. A typical example can look like this:

```javascript
{
  "private": true,
  "devDependencies": {
    "coldbox-elixir": "^3.0.0"
  }
}
```

It defines ColdBox Elixir as a dev dependency. You may then install the dependencies it references by running:

```
npm install
```

This will install ColdBox Elixir and its dependencies into the `node_modules` folder in your root. This folder has been already added to the `.gitignore` file as well, so no need to further ignore it.


# Running Elixir

Elixir is built on top of Webpack, so to run your Elixir tasks you only need to run the `webpack` command in your terminal. Before running Webpack, you will need a `webpack.config.js` file in the root of your project. Below is a simple example:

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.js("app.js");
});
```

Please note that by adding the `-p` flag to the command will turn on Webpack's production mode. This will minify your CSS and JavaScript files as well as add long-term caching hashes to your compiled files.

## Watching Assets For Changes

For performance and convienence, you can run Webpack in watch mode by passing the `-w` or `--watch` flag. Any changes to your source files will automatically re-run your build. Note that your build will be significantly faster on subsequent changes than when running Webpack from scratch.

## NPM Scripts

The easiest way to run Webpack is to set up some NPM scripts. Here are the following we recommend:

```javascript
"scripts": {
    "dev": "webpack --hide-modules",
    "watch": "npm run dev -- --watch",
    "prod": "npm run dev -- -p"
}
```

Then from the terminal you can run `npm run [scriptName for this example either dev, watch or prod]` to run the associated script.


# Configuration Options

All of Elixir's configuration is to support Webpack. Most of the custom changes you will make to Elixir will come through the `mergeConfig` method.

```javascript
const elixir = require("coldbox-elixir");

elixir.config.mergeConfig({});
```

The `mergeConfig` method will intelligently merge your new config with the existing Webpack config (thanks to [`webpack-merge`](https://github.com/survivejs/webpack-merge)).

There are a few additional config options on the Elixir object.

* `elixir.isProduction`
  * By default checks for the production flag from the terminal (`-p`)
* `elixir.rootPath`
  * The root of the project
* `elixir.config`
  * A configured instance of `ElixirConfig`
* `elixir.versioning`
  * Defaults to `elixir.isProduction`


# Working With Stylesheets

## Working With Stylesheets

Elixir processes all CSS files through Webpack. This brings with it some nifty Webpack properties such as [automatic url resolution](https://github.com/webpack-contrib/css-loader).

## CSS

> Due to the way Webpack processes css files, you can no longer have a css file named `vendor`.

You can mix traditional css with webpack using `mix.css`. You can pass one file or an array of files.

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.css("app.css");
    mix.css([
        "node_modules/normalizecss/normalize.css"
        "resources/assets/css/normalize_overrides.css"
    ], {
        name: "normalize.css",
        entryDirectory: ""
    });
});
```

`mix.css` accepts a configuration object as the second parameter:

```javascript
{
    name: this.withoutExtension(filename),
    outputDirectory: "includes/css/",
    entryDirectory: "resources/assets/css/"
}
```

## PostCSS

If you add a `postcss.config.js` file to the root of your project, Elixir will process all of your styles through PostCSS. To learn more about PostCSS, visit [their documentation](https://postcss.org/).

## Sass

The `sass` method allows you to compile [Sass](http://sass-lang.com/) into CSS. Assuming your Sass files are stored at `resources/assets/sass`, you may use the method like so:

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.sass("app.scss");
});
```

Like the `css` method you may compile multiple Sass files into a single CSS file, and even customize the output directory of the resulting CSS:

```
elixir( function( mix ){
    mix.sass([
        "app.scss",
        "controllers.scss"
    ], {
        outputDirectory: "public/assets/css"
    });
} );
```

## Other Pre-processors

Elixir can be extended with any other pre-processor you would like. See our docs on [writing your own extensions](/v3/writing_elixir_extensions) for others!


# Working With Scripts

You can compile scripts using the `mix.js` method. It accepts either a single file or an array of files to combine. Each file will be crawled for dependencies by Webpack.

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.js("app.js");
    mix.js([
        "node_modules/jquery/dist/jquery.min.js",
        "node_modules/bootstrap-sass/assets/javascripts/bootstrap.min.js"
    ], {
        name: "bootstrap",
        entryDirectory: ""
    });
});
```

The second argument to `mix.js` is a configuration object.

```javascript
{
    name: this.withoutExtension(filename),
    outputDirectory: "includes/js/",
    entryDirectory: "resources/assets/js/"
}
```

## `runtime.js` and `vendor.js`

Using `mix.js` or any methods that depend on it create up to two additional files that you should be aware of: `runtime.js` and `vendor.js`. `runtime.js` is the Webpack runtime and should be included as the first script on your page. Without this script, your other files will fail silently. The `vendor.js` is comprised of any dependencies pulled from `node_modules`. This allows your users to keep using the cached `vendor.js` file even when you change your application code. This file should be included after `runtime.js` and before any of your application code.


# Versioning Cache Busting

By default, Elixir will version all your compiled assets when compiling for production `webpack -p`.

This produces a file with a unique hash in the filename. This hash will only change if the contents of the file change.

You can change or turn off the versioning by setting the `elixir.versioning` property in your `webpack.config.js` file.

Additionally, Elixir will generate an `/includes/manifest.json` file. This file maps the original file name to the hashed file name. This lets you still use the original file name in your code and not have to update your templates whenever your assets change.

ColdBox (5.1+) ships with some helper methods for this purpose. You can also copy the code below for use in your own projects.

```javascript
<cfscript>
    /**
    * Adds the versioned path for an asset to the view
    * @filename The asset path to find relative to the includes convention directory
    * @buildDirectory The build directory inside the includes convention directory
    * @sendToHeader Send to the header via htmlhead by default, else it returns the content
    * @async HTML5 JavaScript argument: Specifies that the script is executed asynchronously (only for external scripts)
    * @defer HTML5 JavaScript argument: Specifies that the script is executed when the page has finished parsing (only for external scripts)
    */
    function elixir(
        required filename,
        boolean sendToHeader=true,
        boolean async=false,
        boolean defer=false
    ){
        html.addAsset(
            elixirPath( arguments.fileName ),
            arguments.sendToHeader,
            arguments.async,
            arguments.defer
        );

        return this;
    }

    /**
    * Finds the versioned path for an asset if leveraging ColdBox Elixir
    * @returns The path
    */
    string function elixirPath( required string fileName ){
        var includesConvention     = "includes";
        var mapping             = event.getCurrentModule() != "" ? event.getModuleRoot() : controller.getSetting( "appMapping" );
        var filePath             = expandPath( "#mapping#/#includesConvention#/manifest.json" );
        var href                 = "#mapping#/#includesConvention#/#arguments.fileName#";

        if ( ! fileExists( filePath ) ) {
            return href;
        }

        var fileContents = fileRead( filePath );
        if ( ! isJSON( fileContents ) ) {
            return href;
        }

        var json = deserializeJSON( fileContents );
        if ( ! structKeyExists( json, arguments.fileName ) ) {
            return href;
        }

        return "#mapping#/#includesConvention#/#json[ arguments.fileName ]#";
    }
</cfscript>
```

You can then just use them in your layouts or views to include versioned files:

```markup
<head>
    #elixir( "css/myapp.css" )#
</head>
<body>
    <!-- ... -->

    <script src="#elixirPath( "js/app.js" )#"></script>
</body>
```


# Mixing in tasks from ColdBox Modules

ColdBox Modules can be an excellent way to structure your project, and ColdBox Elixir is the perfect companion. Use all the Elixir methods you know and love in your modules, and Elixir will build them all for you with just one command.

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.modules();
});
```

## `elixir-module.js`

To specify what Elixir functions to run a module needs to define an `elixir-module.js` file. This file looks very similar to your `webpack.config.js`. Here is an example of one:

```javascript
module.exports = mix => {
    mix.sass("app.scss");
};
```

The function here is exactly the same function you would write inside the `elixir` call in your main `webpack.config.js` file. Every method installed in your main `webpack.config.js` file is available here.

Elixir will scope the changes to the current module's directory. This means, for example, that:

```javascript
mix.sass("app.scss");
```

Inside of a module with a path `/modules_app/my-module/elixir-module.js` will look for an `app.scss` file inside of `/modules_app/my-module/resources/assets/sass/app.scss` and compile it to `/modules_app/my-module/includes/css/app.css`.

### Includes, Excludes, and File name

You can specify and array of folders to include, folders to exclude, or change the default file name if you wish:

| Argument   | Default Value      |
| ---------- | ------------------ |
| `includes` | `["modules_app"]`  |
| `excludes` | `[]`               |
| `fileName` | `elixir-module.js` |

## Running a Single Module

You can compile a single module's assets by using `mix.module()` passing in the module's name:

```javascript
// /gulpfile.js
elixir(mix => {
    mix.module("my-module");
});
```

This will look for the following file: `/modules_app/my-module/elixir-module.js` and add the resulting mix function to the gulp tasks. If the file does not exist or is not a function, Elixir will show an error and continue on with the other build tasks.

The second parameter is a configuration object to change the folderName or fileName to look for:

```javascript
elixir(mix => {
    mix.module("my-module", {
        folderName: "new_base_directory",
        fileName: "new-filename.js"
    });
});
```

This would look in `/new_base_directory/my-module/new-filename.js` for the mix function.

## Module alias

If you want use alias for your import in a module, you must use:

```javascript
import store from '@moduleName/store.js'
```


# ContentBox Integration

ColdBox Elixir has a few helper methods when working in a ContentBox app.

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.themes();
    mix.contentbox();
});
```

These two methods work just like a call to `mix.modules` with some different defaults set.

> For a refresher on how `mix.modules` and `elixir-module.js` files work, see the [modules docs.](/v3/coldbox_modules)

## `mix.themes`

This method will look inside the `modules_app/contentbox-custom/_themes` directory for any folders with a `elixir-theme.js` file. The `elixir-theme.js` file is identical to a `elixir-module.js` file.

## `mix.contentbox`

This method will look inside the `modules_app/contentbox-custom/_modules` directory for any folders with a `elixir-module.js` file.


# Copying Files & Directories

The `copy` method may be used to copy files and/or directories to new locations. All operations are relative to the project's `root` directory:

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.copy("resources/vendor/foo/bar.css", "includes/css/bar.css");
});
```


# Deleting Files & Directories

By default the following directories are cleaned out for each build:

```
"includes/js"
"includes/css"
"includes/fonts"
"includes/media"
"includes/images"
```

If you would like to add additional directories, you can do so by configuring a new instance of the `CleanWebpackPlugin`:

```javascript
const elixir = require("coldbox-elixir");
const CleanWebpackPlugin = require("clean-webpack-plugin");

elixir.config.mergeConfig({
    plugins: [
        new CleanWebpackPlugin(["my/custom/directory"], { root: elixir.rootPath })
    ]
});
```


# Environment Variables

You will occassionally need to access environment variables in your JavaScript.  This is done using the `process.env` object like so: `process.env.YOUR_KEY_HERE`. But your user's browser won't have access to a `process` object.  How will we handle this?

### Webpack's EnvironmentPlugin

Webpack uses the [`EnvironmentPlugin`](https://webpack.js.org/plugins/environment-plugin/) to do this.  It takes an array of environment variable names to allow in your application.  Then all instances of `process.env.YOUR_KEY_HERE` will be replaced with the value in your environment.&#x20;

{% code title="Environment" %}

```bash
NODE_ENV=development
```

{% endcode %}

{% code title="webpack.config.js" %}

```javascript
module.exports = {
  // ...
  plugins: [
    // ...
    new webpack.EnvironmentPlugin(["NODE_ENV"]),
  ]
};
```

{% endcode %}

{% code title="Source File" %}

```javascript
console.log(process.env.NODE_ENV);
```

{% endcode %}

{% code title="Output File" %}

```javascript
console.log("development");
```

{% endcode %}

If the environment variable allowed is missing, an error will be thrown during compilation, ensuring that you don't accidentally ship code without this value.

In addition to passing an array of key names, you may pass an object with the keys being environment variable names and the values being default values if the keys are not found in the environment.

{% code title="webpack.config.js" %}

```javascript
module.exports = {
  // ...
  plugins: [
    // ...
    new webpack.EnvironmentPlugin({
      NODE_ENV: "development"
    }),
  ]
};
```

{% endcode %}

### mix.env

To make this process easier, Elixir has a `mix.env` method that passes through to `EnvironmentPlugin`.

{% code title="webpack.config.js" %}

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
  mix.env(["NODE_ENV"]);  
});
```

{% endcode %}

This is the easiest way to define the environment variables your JavaScript bundle needs.

### Automatic NODE\_ENV

`NODE_ENV` is a very common environment variable used by many libraries to output additional debugging information or to enable optimizations.  Since Elixir already knows what environment you are building for, this value is defaulted for you.  If you desire to override that value, just define `NODE_ENV` in your environment and it will take precendence.


# BrowserSync

[BrowserSync](https://www.browsersync.io/) automatically refreshes your web browser after you make changes to your front-end resources. You can use the `browserSync` method to instruct Elixir to start a BrowserSync server when you run the `gulp watch` command:

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.browserSync();
});
```

After running this command you will see directions to add a script tag to the bottom of your website like this:

```bash
[BS] Copy the following snippet into your website, just before the closing </body> tag
<script id="__bs_script__">//<![CDATA[
    document.write("<script async src='http://HOST:3000/browser-sync/browser-sync-client.2.12.5.js'><\/script>".replace("HOST", location.hostname));
//]]></script>
```

Add that snippet to your `layouts/Main.cfm` file and reload to enable BrowserSync!

## Specifying a Proxy

Instead of copying the script tag into you app, you can tell BrowserSync to proxy your existing CFML server:

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.browserSync({
        proxy: "localhost:50608"
    });
});
```

Running `webpack -w` will now open up `localhost:3000` which proxies to your app! No need for that BrowserSync script tag anymore!

## Default Options

We define a number of default options for BrowserSync:

```javascript
{
    host: "localhost",
    port: 3000,
    proxy: "http://localhost:8888",
    files: "**/*"
}
```

The can be overridden by passing in an options object as the only parameter (as seen above with `proxy`).

## Custom Options

In addition to the `proxy` option, you may pass any BrowserSync option here as the only argument. A list of the BrowserSync options can be found [here](http://www.browsersync.io/docs/options/).


# Vue.js Integration

ColdBox Elixir lets you work with `.vue` files out of the box.

You will begin by installing Vue.js via npm: `npm install vue`. This will add `Vue` as a dependency for your project in your project's `package.json` and into the `node_modules` directory. The following is the `package.json` you should use when integrating with Vue.js:

**package.json**

```javascript
{
  "private": true,
  "devDependencies": {
    "coldbox-elixir": "3.0.0",
  },
  "dependencies": {
    "vue": "^2.0.0"
  }
}
```

Then create your normal JavaScript and Vue components in your `resources/assets/js` folder.

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.vue("app.js");
});
```

Your `App.js` can look like this:

**resources/assets/js/App.js**

```javascript
import Vue from "vue";

new Vue({
  el: "#app",
  data: {
    message: "Hello, world!"
  }
});
```

And you can import any components following the same relative path of the `resources/assets/js` folder.

You can also use the optional `.vue` syntax which allows you to co-locate your template, styles, and scripts in a single-file component.

**resources/assets/js/App.js**

```javascript
import Vue from "vue";
import Profile from "./components/Profile.vue";

new Vue({
  el: "#app",
  components: { Profile }
});
```

**resources/assets/js/components/Profile.vue**

```
<template>
  <div class="profile">
    {{ name }}
  </div>
</template>

<script>
export default {
  data () {
    return {
      name: "Luis Majano"
    };
  }
};
</script>

<style>
.profile {
    background: #eee;
    border: 1px solid #aaa;
    border-radius: 2em;
    margin: 2em auto;
    min-height: 150px;
    padding: 2em;
    width: 300px;
}
</style>
```

You would then use this in your ColdBox layout or view like so:

```markup
<div id="app">
    <profile></profile>
</div>
<script src="/includes/js/App.js"></script>
```

Any style blocks in your `.vue` components will be extracted as well to the same directory as your javascript file as a css file. For example, if you were compiling `mix.vue( "app.js" )` Elixir would generate a `includes/js/app.css` file containing the css for the style blocks used in that entrypoint.

> Note: there are some drawbacks with style blocks in Vue components and Elixir. if you are creating multiple entry points with multiple `mix.vue` calls, any style blocks in shared components will be duplicated in each of the css files. Additionally, because Elixir is already extracting other css files, style blocks in Vue components are always extracted. For these reasons, we recommend using other approaches to managing your css with Vue components and Elixir.


# Writing Elixir Extensions

## `mergeConfig`

Occasionally you will need to extend Webpack in ways not supported by ColdBox Elixir. In these moments, you can provide your own configuration using the `mergeConfig` method.

```javascript
const elixir = require("coldbox-elixir");

elixir.config.mergeConfig({
    // custom webpack config goes here
});
```

The `mergeConfig` method will merge the object provided with the existing Webpack config using the excellent [`webpack-merge` library](https://github.com/survivejs/webpack-merge).

## Custom Ingredients

Ingredients are the name for the methods available on the `mix` object. You can add an ingredient to your Elixir instance like so:

```javascript
const elixir = require("coldbox-elixir");

elixir.config.addIngredient("nameOfIngredient", () => {
    // function to run when called (mix.nameOfIngredient());
    // any parameters passed to the `mix.nameOfIngredient()` call will be available in the function.
    // The `this` scope refers to the ElixirConfig object, so methods like `this.mergeConfig` are available.
})
```

The main use cases for using an ingredient over custom config are:

1. Need to call multiple times each time for different file(s)
2. Want to re-use across projects

Especially in the second case, feel free to publish the ingredient on NPM if you feel it could be useful to other developers.


# Introduction

```
 _______        _____ _     _ _____  ______
 |______ |        |    \___/    |   |_____/
 |______ |_____ __|__ _/   \_ __|__ |    \_
```

## Welcome to ColdBox Elixir

![ColdBox Platform](https://61079082-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LA-UVvDWU72L1kpFjM1%2F-LWkzM8VOyxS-kRXLP-n%2F-LWkzNotvPLzUkiDRhDt%2FColdBoxLogo2015_300.png?generation=1548083894454495\&alt=media)

ColdBox Elixir provides a clean, fluent API for defining basic [Gulp](http://gulpjs.com/) tasks for your ColdBox applications. This project was forked from the [Laravel Elixir](https://github.com/laravel/elixir) project, so many many thanks for all their hard work and ideas.

### Versioning

ColdBox Elixir is maintained under the [Semantic Versioning](http://semver.org) guidelines as much as possible.Releases will be numbered with the following format:

```
<major>.<minor>.<patch>
```

And constructed with the following guidelines:

* Breaking backward compatibility bumps the major (and resets the minor and patch)
* New additions without breaking backward compatibility bumps the minor (and resets the patch)
* Bug fixes and misc changes bumps the patch

### License

MIT License: [https:\\/\\/opensource.org\\/licenses\\/MIT](https://opensource.org/licenses/MIT).

### Important Links

* Code: [http:\\/\\/github.com\\/coldbox-elixir\\/core](http://github.com/coldbox-elixir/core)
* Issues: [http:\\/\\/github.com\\/coldbox-elixir\\/core\\/issues](http://github.com/coldbox-elixir/core/issues)
* Documentation: [http:\\/\\/coldbox-elixir.ortusbooks.com](http://coldbox-elixir.ortusbooks.com)

### Professional Open Source

![Ortus Solutions, Corp](https://61079082-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LA-UVvDWU72L1kpFjM1%2F-LWkxkk5Z2IgYpQgjfcD%2F-LWkxmgjWgRMMVIuYEU1%2Fortussolutions_button.png?generation=1548083474248516\&alt=media)

ColdBox Elixir is a professional open source software backed by [Ortus Solutions, Corp](http://www.ortussolutions.com/services) offering services like:

* Custom Development
* Professional Support & Mentoring
* Training
* Server Tuning
* Security Hardening
* Code Reviews
* [Much More](http://www.ortussolutions.com/services)

#### HONOR GOES TO GOD ABOVE ALL

Because of His grace, this project exists. If you don't like this, then don't read it, it's not for you.

> "Therefore being justified by **faith**, we have peace with God through our Lord Jesus Christ: By whom also we have access by **faith** into this **grace** wherein we stand, and rejoice in hope of the glory of God." Romans 5:5


# Overview

Here is a quick overview of how ColdBox Elixir works.

## How it works

Elixir supports several common CSS pre-processors, JavaScript compilers, and TestBox runner integrations. By leveraging Gulp and the `Gulpfile.js` configuration file, Elixir will allow you to fluently define your asset pipeline using conventions.

## Conventions

All resources in your ColdBox application will be stored under the `resources/assets` folder. Under this folder you can find several sub-sections:

* `css` - Where you can store your css
* `js` - Where you can store your js, vue.js and more
* `less` - Where you can store your less files
* `sass` - Where you can store your sass files

Depending on the formulas you mix up in the `Gulpfile.js` using Elixir, you will end up with all your assets linted, minified, etc in their appropriate destination in the `includes` folder:

* `css` - Destination for css
* `js` - Destination for js
* `build` - Destination for versioned assets

For example:

```javascript
var elixir = require( "coldbox-elixir" );
elixir( function( mix ) {
        // Look in the "resources/sass" folder
    mix.sass( "app.scss" )
        // Look in the "resourcess/css" folder
       .styles( "modules.css" );
});       
// Elixir will then output all assets to ColdBox 'includes' folder by convention.
```

If you've ever been confused about how to get started with Gulp and asset compilation, you will love ColdBox Elixir. However, you are not required to use it while developing your application. You are free to use any asset pipeline tool you wish, or even none at all.


# Changelog

## 2.0.0

* Updated to stay current with Laravel Elixir 6.0.0.
* Deprecated `mix.babel()` in favor of `mix.browserify()`, `mix.webpack`, `mix.rollup`, or similar module bundlers.
* Nicer console output.
* Broke out first party extensions from the core (to keep in line with Laravel Elixir 6.0.0)
  * [`coldbox-elixir-browserify`](https://github.com/coldbox-elixir/extension-browserify)
  * [`coldbox-elixir-browsersync`](https://github.com/coldbox-elixir/extension-browsersync)
  * [`coldbox-elixir-rollup`](https://github.com/coldbox-elixir/extension-rollup)
  * [`coldbox-elixir-stylus`](https://github.com/coldbox-elixir/extension-stylus)
  * [`coldbox-elixir-vue`](https://github.com/coldbox-elixir/extension-vue)
  * [`coldbox-elixir-webpack`](https://github.com/coldbox-elixir/extension-webpack)
* Helpful warnings when trying to use methods provided by a first party extension.

## 1.1.0

* Travis Support
* BDD via TestBox fixes
* Updated all dependencies to latest versions
* Gulp tasks for compilation, tests and watchers
* Test App additions for testing direct gulp integrations
* If not tasks defined in the user's gulpfile, just a message is shown instead of an exception
* Removed coffeescript support, no longer needed
* Added new config map for `appPaths` to support all ColdBox conventions
* Vueify core support view browserify for Vue.js components
* Included a new `template` folder which helps setting up new elixir based projects

## 1.0.0

* Initial Port to ColdBox


# Installation

## Installing Node

Before triggering Elixir, you must first ensure that [Node.js](https://nodejs.org/en/) is installed on your machine.

```
node -v
```

## Installing Gulp

Next, you'll want to pull in Gulp as a global NPM package so you have it available for any ColdBox application.

```
npm install -g gulp
```

If you use a version control system, you may wish to run the npm [shrinkwrap](https://docs.npmjs.com/cli/shrinkwrap) to lock your NPM requirements:

```
npm shrinkwrap
```

Once you have run this command, feel free to commit the `npm-shrinkwrap.json` into source control.

## Installing ColdBox Elixir

The only remaining step is to install Elixir! If you generate a ColdBox application using any of our [elixir templates](https://github.com/coldbox-templates/) then you will find a `package.json` file in the root of the application already. Think of this like your `box.json` file, except it defines Node dependencies instead of ColdFusion (CFML) dependencies. A typical example can look like this:

```javascript
{
  "private": true,
  "devDependencies": {
    "gulp": "^3.9.1"
  },
  "dependencies": {
    "bootstrap-sass": "^3.3.6",
    "coldbox-elixir": "^2.1.0",
    "jquery": "^2.2.3"
  }
}
```

It defines ColdBox Elixir, Bootstrap and jQuery as your dependencies. You may then install the dependencies it references by running:

```
npm install
```

Please note that jQuery and Bootstrap are added for convenience, they are not needed for ColdBox Elixir. So feel free to remove them or add any other UI dependency you like.

This will install ColdBox Elixir, Bootstrap and jQuery into the `node_modules` folder in your root. This folder has been already added to the `.gitignore` file as well, so no need to further ignore it.

> **Note** : If you are developing on a Windows system or you are running your VM on a Windows host system, you may need to run the `npm install` command with the `--no-bin-links` switch enabled: `npm install --no-bin-links`

> **Tip** : If you are integrating with Vue.js, please see our [Vue.js](/v2/vuejs_integration) section


# Running Elixir

Elixir is built on top of Gulp, so to run your Elixir tasks you only need to run the `gulp` command in your terminal, as you will already have a `Gulpfile.js` in your project root that will resemble the following:

```javascript
var elixir = require( "coldbox-elixir" );

/*
 |--------------------------------------------------------------------------
 | Elixir Asset Management
 |--------------------------------------------------------------------------
 |
 | Elixir provides a clean, fluent API for defining some basic Gulp tasks
 | for your ColdBox application. By default, we are compiling the Sass
 | file for our application, as well as publishing vendor resources.
 |
 */

elixir( function( mix ){

} );
```

Please note that by adding the `--production` flag to the command will instruct Elixir to minify your CSS and JavaScript files:

```bash
// Run all tasks...
gulp

// Run all tasks and minify all CSS and JavaScript...
gulp --production
```

You can also programmatically add a production flag into your `Gulpfile.js` by using the configuration option: `elixir.config.production` boolean flag.

## Watching Assets For Changes

Since it is inconvenient to run the gulp command on your terminal after every change to your assets, you may use the `gulp watch` command. This command will continue running in your terminal and watch your assets for any changes. When changes occur, new files will automatically be compiled or tested:

```
gulp watch
```


# Configuration Options

## Configuration Options

Elixir comes with a preset of configuration options that you can find under our `dist/Config.js` file. Below is the contents of the default Elixir configuration file:

```javascript
    /*
     |----------------------------------------------------------------
     | Master Configuration
     |----------------------------------------------------------------
     |
     | This file contains the proper paths and options for each and
     | and every Gulp task that Elixir wraps up. To override any
     | setting, reference elixir.config.* from your Gulpfile.
     |
     | Alternatively you may create an elixir.json file within your
     | project root. As JSON, modify any settings contained here
     | and they'll take precedence over these defaults. Easy!
     |
     */

    const config = {

        /*
         |----------------------------------------------------------------
         | Production Mode
         |----------------------------------------------------------------
         |
         | Elixir will trigger certain actions, dependent upon this flag.
         | You may enable this mode by triggering "gulp --production",
         | enabling things like CSS and JS minification. EasyPeasy!
         |
         */

        production: Elixir.inProduction,

        /*
         |----------------------------------------------------------------
         | Assets Path
         |----------------------------------------------------------------
         |
         | This assets path property is prefixed to all relevant assets
         | in your application. For example, "resources/assets/sass"
         | or "resources/assets/coffee." Change this if you must.
         |
         */

        assetsPath: 'resources/assets',

        /*
         |----------------------------------------------------------------
         | Public Path
         |----------------------------------------------------------------
         |
         | Much like assets path, this public path property is prefixed to
         | any paths in your application, that point to the public dir.
         | It's useful, when a server requires a unique public path.
         |
         */

        publicPath: 'includes',

        /*
         |----------------------------------------------------------------
         | App Path
         |----------------------------------------------------------------
         |
         | The app path, you guessed it, specifies the path to the app
         | folder in your project. If using ColdBox, then you won't
         | need to modify this path. Otherwise modify as needed.
         |
         */

        appPaths : {
            "root"          : "",
            "config"        : "config",
            "handlers"      : "handlers",
            "interceptors"  : "interceptors",
            "layouts"       : "layouts",
            "models"        : "models",
            "modules"       : "modules",
            "modules_app"   : "modules_app",
            "tests"         : "tests"
        },

        /*
         |----------------------------------------------------------------
         | View Path
         |----------------------------------------------------------------
         |
         | Very likely, you will never need/want to modify this property.
         | However, for the instances where your app's views directory
         | is located in a different spot, please modify as needed.
         |
         */

        viewPaths: {
            "views"   : "views",
            "layouts" : "layouts"
        },

        /*
         |----------------------------------------------------------------
         | Notifications
         |----------------------------------------------------------------
         |
         | As a convenience, Elixir will, when available, automatically
         | display OS notifications upon the completion of any task.
         | But of course you're free to disable this, if needed.
         |
         */

        notifications: true,

        /*
         |----------------------------------------------------------------
         | Log Muted
         |----------------------------------------------------------------
         |
         | As a convenience, Elixir will, when available, automatically
         | display OS log upon the completion of any task.
         | But of course you're free to disable this, if needed.
         |
         */
        muted: process.argv[1].indexOf('bin/_mocha') > -1,

        /*
         |----------------------------------------------------------------
         | Sourcemaps
         |----------------------------------------------------------------
         |
         | A sourcemap is a JSON mapping, which declares a relationship
         | between a minified file and its original source location.
         | Quite useful for debugging, it's turned on by default.
         |
         */

        sourcemaps: ! Elixir.inProduction,

        /*
         |----------------------------------------------------------------
         | File System Event Batching
         |----------------------------------------------------------------
         |
         | You likely won't need to modify this object. That said, should
         | you need to, these settings are exclusive to the watch task.
         | They set the limit and timeout for running batch-updates.
         |
         */

        batchOptions: {
            // https://github.com/floatdrop/gulp-batch#batchoptions-callback-errorhandler
            limit: undefined,
            timeout: 1000
        },

        css: {

            /*
             |----------------------------------------------------------------
             | CSS Source Folder
             |----------------------------------------------------------------
             |
             | This property declares the root folder for all vanilla CSS
             | files. Note that this is the folder name, not the path.
             | We'll stick with a general "css" name - makes sense.
             |
             */

            folder: 'css',

            /*
             |----------------------------------------------------------------
             | CSS Output Folder
             |----------------------------------------------------------------
             |
             | Generally, your source files will be stored outside of your
             | public directory, and then compiled/merged as necessary.
             | This property represents the public specific folder.
             |
             */

            outputFolder: 'css',

            /*
             |----------------------------------------------------------------
             | CSS3 Autoprefixing
             |----------------------------------------------------------------
             |
             | When working with any form of CSS, Elixir automatically runs
             | your file through a CSS autoprefixer, which automatically
             | adds or removes vendor-specific CSS3 prefixes. Useful!
             |
             */

            autoprefix: {
                enabled: true,

                // https://www.npmjs.com/package/gulp-autoprefixer#api
                options:  {
                    browsers: ['> 1%'],
                    cascade: false
                }
            },

            /*
             |----------------------------------------------------------------
             | CSS3 Minification
             |----------------------------------------------------------------
             |
             | When running Gulp with the production flag, any CSS will
             | automatically be minified. This offers the benefit of
             | reduced file sizes. Adjust any plugin option here.
             |
             */

            minifier: {
                // https://github.com/jakubpawlowicz/clean-css#how-to-use-clean-css-api
                pluginOptions: {}
            },

            /*
             |----------------------------------------------------------------
             | Sass Compilation
             |----------------------------------------------------------------
             |
             | Gone are the days of researching how to call Sass on a given
             | folder. Simply run `mix.sass('file.scss')` and you're all
             | set. This object sets the folder name and plugin opts.
             |
             */

            sass: {
                folder: 'sass',

                search: '/**/*.+(sass|scss)',

                // https://github.com/sass/node-sass#options
                pluginOptions: {
                    outputStyle: Elixir.inProduction ? 'compressed' : 'nested',
                    precision: 10
                }
            },

            /*
             |----------------------------------------------------------------
             | Less Compilation
             |----------------------------------------------------------------
             |
             | Gone are the days of researching how to call Less on a given
             | folder. Simply run `mix.less('file.less')` and you're all
             | set. This object sets the folder name and plugin opts.
             |
             */

            less: {
                folder: 'less',

                search: '/**/*.less',

                // https://github.com/plus3network/gulp-less#options
                pluginOptions: {}
            }
        },

        js: {

            /*
             |----------------------------------------------------------------
             | JavaScript Source Folder
             |----------------------------------------------------------------
             |
             | Much like the CSS folder option above, this property sets the
             | name of the folder, not the full path, for your JavaScript
             | source files. It then gets affixed to the "assetsPath".
             |
             */

            folder: 'js',

            /*
             |----------------------------------------------------------------
             | JavaScript Output Folder
             |----------------------------------------------------------------
             |
             | Once your vanilla JavaScript files have been compiled/merged,
             | they will be saved to your public directory. This property
             | represents the name of the folder within that location.
             |
             */

            outputFolder: 'js',

            /*
             |----------------------------------------------------------------
             | UglifyJS Parser/Compressor/Beautifier
             |----------------------------------------------------------------
             |
             | UglifyJS is a JavaScript parser/compressor/beautifier.
             | It'll minify your JavaScript with ease and has an option to
             | mangle your code.
             |
             */

            uglify: {
                options: {
                    compress: {
                        drop_console: Elixir.inProduction
                    }
                }
            }
        },

        testing: {

            /*
             |----------------------------------------------------------------
             | TestBox Autotesting
             |----------------------------------------------------------------
             |
             | Want to automatically trigger your TestBox tests? Not a problem.
             | This object stores your default TestBox directory path. For a
             | custom command, you may use the second arg to mix.testbox.
             |
             */

            testbox: {
                path: 'tests/specs',
                search: '/**/*.cfc',
                command: 'box testbox run'
            },

        },

        /*
         |----------------------------------------------------------------
         | File Versioning
         |----------------------------------------------------------------
         |
         | If you use aggressive assets caching on your server, then you
         | will need a way to cachebust, right? No querystring needed
         | this time. Here you may set the default "build" folder.
         |
         */

        versioning: {
            buildFolder: 'build'
        },

        /*
         |----------------------------------------------------------------
         | Browsersync
         |----------------------------------------------------------------
         |
         | Want to have your browser refresh instantly upon changing a bit
         | of Sass or modifying a view? With Elixir, it has never been
         | easier. This contains default options for the extension.
         |
         */

        browserSync: {
            // http://www.browsersync.io/docs/options/
            reloadOnRestart : true,
            notify: true,
            // without this, the path seems to be relative to the proxied app (which won't work)
            scriptPath: function( path, port, options ) {
                return options.get( "absolute" );
            }
        },

        /*
         |----------------------------------------------------------------
         | Watch
         |----------------------------------------------------------------
         |
         | Configure how your filesystem is monitored for changes. This
         | modifies the behavior of any task using "watch."
         |
         */

        watch: {
            // https://www.npmjs.com/package/gulp-watch/#options
            interval: 1000,
            usePolling: true
        }
    };
```

## Overriding Configuration Options

You can override or add configuration options in your `Gulpfile.js` by referencing the `elixir.config.*` keys.

```javascript
elixir.config.production = true;
```


# Working With Stylesheets

## Working With Stylesheets

The `Gulpfile.js` file in your project's root directory contains all of your Elixir tasks. Elixir tasks can be chained together to define exactly how your assets should be compiled. Please note that when working with any form of CSS, Elixir automatically runs your file through a CSS [autoprefixer](https://www.npmjs.com/package/gulp-autoprefixer), which automatically adds or removes vendor-specific CSS3 prefixes.

> **Tip**: Please remember you can use any valid [file globbing](https://github.com/isaacs/node-glob) pattern as well.

## Less

To compile [Less](http://lesscss.org/) into CSS, you may use the `less` method. The `less` method assumes that your Less files are stored in `resources/assets/less`. By default, the task will place the compiled CSS for this example in `includes/css/app.css`:

```javascript
elixir( function( mix ){
    mix.less( "app.less" );
} );
```

You may also combine multiple Less files into a single CSS file. Again, the resulting CSS will be placed in `includes/css/app.css`:

```javascript
elixir( function( mix ){
    mix.less( [
        "app.less",
        "controllers.less"
    ] );
} );
```

If you wish to customize the output location and/or name of the compiled CSS, you may pass a second argument to the `less` method:

```javascript
elixir( function( mix ){
    mix.less( "app.less", "includes/stylesheets" );
} );

// Specifying a specific custom output filename...
elixir( function( mix ){
    mix.less( "app.less", "includes/stylesheets/style.css" );
} );
```

The third optional argument is the base directory override, you can use it to override the `resources/assets/less` convention.

## Sass

The `sass` method allows you to compile [Sass](http://sass-lang.com/) into CSS. Assuming your Sass files are stored at `resources/assets/sass`, you may use the method like so:

```javascript
elixir( function( mix ){
    mix.sass( "app.scss" );
} );
```

Again, like the `less` method, you may compile multiple Sass files into a single CSS file, and even customize the output directory of the resulting CSS:

```
elixir( function( mix ){
    mix.sass(
        [
            "app.scss",
            "controllers.scss"
        ], 
        "public/assets/css"
    );
} );
```

The third optional argument is the base directory override, you can use it to override the `resources/assets/sass` convention.

## Combine CSS

If you would just like to combine and minify CSS stylesheets into a single file, you may use the `styles` method. Paths passed to this method are relative to the `resources/assets/css` directory and the resulting CSS will be placed in `includes/css/all.css` by convention:

```javascript
elixir( function( mix ){
    mix.styles( [
        "normalize.css",
        "main.css"
    ] );
} );
```

Of course, you may also output the resulting file to a custom location by passing a second argument to the `styles` method:

```javascript
elixir( function( mix ){
    mix.styles(
        [
            "normalize.css",
            "main.css"
        ], 
        "public/assets/css"
   );
} );
```

The third optional argument is the base directory override, you can use it to override the `resources/assets/css` convention.

### Combine Folders

If you need to combine all of the css in a given directory, you may use the `stylesIn` method or globbing patterns. The resulting css will be placed in `includes/css/all.css`:

elixir( function( mix ){ mix.stylesIn( "resources/css/some/directory" ); } );

### Combine CSS From Anywhere

If you have multiple css files that you would like to combine into a single file, you may use the `combine` method as well. Please note that the `combine` method does NOT do any type of compilation or minification. It is a plain 'ol combination or concatenation of files.

The method assumes the starting place of all paths from the `root` of your application, so not the `resources` folder. The first argument is a single location or an array of locations, the second argument is the output combo file.

```javascript
elixir( function( mix ){
    mix.combine( 
        [
            "resources/assets/vendor/date.css",
            "resources/assets/vendor/app.css",
        ],
        "includes/css/combined.css"
    );

    mix.combine( 
        [
            "resources/assets/vendor/*.css"
        ],
        "includes/css/combined.css"
    );
} );
```

## Source Maps

Source maps are enabled out of the box. So, for each file that is compiled you will find a companion `*.css.map` file in the same directory. This mapping allows you to trace your compiled stylesheet selectors back to your original Sass or Less while debugging in your browser.

If you do not want source maps generated for your CSS, you may disable them using a simple configuration option:

```
// No more source maps ma!
elixir.config.sourcemaps = false;

elixir( function( mix ){
    mix.sass( 'app.scss' );
} );
```

## Other Pre-processors

Elixir can be extended with any other pre-processor you would like. Check out [`coldbox-elixir-stylus`](https://github.com/coldbox-elixir/extension-stylus) for an official Stylus extension or see our docs on [writing your own extensions](/v2/writing_elixir_extensions) for others!


# Working With Scripts

Elixir also provides several functions to help you work with your JavaScript files, such as compiling future versions of JavaScript, using module bundlers, minification, and simply concatenating plain JavaScript files:

* `scripts`
* `scriptsIn`
* `webpack`
* `browserify`
* `rollup`

> **Tip**: Please remember you can use any valid [file globbing](https://github.com/isaacs/node-glob) pattern as well.

## Babel

> **Deprecation**: `mix.babel()` has been deprecated in ColdBox Elixir 2.0.0 in favor of using one of the module bundlers ([`browserify`](https://github.com/coldbox-elixir/extension-browserify), [`rollup`](https://github.com/coldbox-elixir/extension-rollup) or [`webpack`](https://github.com/coldbox-elixir/extension-webpack))

## Combining Compiled Scripts

If you have multiple JavaScript files (non babelified) that you would like to combine into a single file, you may use the `scripts` method.

The `scripts` method assumes all paths are relative to the `resources/assets/js` directory, and will place the resulting JavaScript in `includes/js/all.js` by default:

```javascript
elixir( function( mix ){
    mix.scripts( [
        'jquery.js',
        'app.js'
    ] );
} );
```

If you need to combine multiple sets of scripts into different files, you may make multiple calls to the `scripts` method. The second argument given to the method determines the resulting file name for each concatenation. You can also use the third optional argument to override the base directory of `resources/assets/js`

```
elixir( function( mix ){
    mix.scripts( ['app.js', 'controllers.js' ], 'public/js/app.js' )
       .scripts( ['forum.js', 'threads.js' ], 'public/js/forum.js' );
});
```

If you need to combine all of the scripts in a given directory, you may use the `scriptsIn` method or globbing patterns. The resulting JavaScript will be placed in `includes/js/all.js`:

```javascript
elixir( function( mix ){
    mix.scriptsIn( 'resources/js/some/directory' );
} );
```

## Combining Scripts

If you have multiple JavaScript files that you would like to combine into a single file, you may use the `combine` method. Please note that the `combine` method does NOT do any type of compilation or minification. It is a plain 'ole combination or concatenation of files.

The method assumes the starting place of all paths from the `root` of your application, so not the `resources` folder. The first argument is a single location or an array of locations, the second argument is the output combo file.

```javascript
elixir( function( mix ){
    mix.combine( 
        [
            'resources/assets/vendor/jquery.js',
            'resources/assets/vendor/app.js',
        ],
        "includes/js/combined.js"
    );

    mix.combine( 
        [
            'resources/assets/vendor/*.js'
        ],
        "includes/js/combined.js"
    );
} );
```

## Module Bundlers

There is official support for three module bundlers:

* [Browserify](https://github.com/coldbox-elixir/extension-browserify)
* [Rollup](https://github.com/coldbox-elixir/extension-rollup)
* [Webpack](https://github.com/coldbox-elixir/extension-webpack)

See each individual repository for their specific API.

## Browserify

Elixir ships with a [browserify](http://browserify.org/) method, which gives you all the benefits of requiring modules in the browser and using [ECMAScript 6](https://babeljs.io/docs/learn-es2015/) and [JSX](https://facebook.github.io/react/docs/jsx-in-depth.html).

This task assumes that your scripts are stored in `resources/assets/js` and will place the resulting file in `includes/js/main.js`. You may pass a custom output location as an optional second argument and an optional third argument to override the base directory of `resources/assets/js`:

```
elixir( function( mix ){

 mix.browserify( 'main.js' );

} );



// Specifying a specific output filename...

elixir( function( mix ){

 mix.browserify( 'main.js', 'includes/javascripts/main.js' );

} );



// Specifying a specific output filename + basedir

elixir( function( mix ){

 mix.browserify( 'main.js', 'includes/javascripts/main.js', 'public/js' );

} );
```


# Versioning Cache Busting

Many developers suffix their compiled assets with a timestamp or unique token to force browsers to load the fresh assets instead of serving stale copies of the code. Elixir can handle this for you using the `version` method.

The `version` method accepts a file name relative to the `includes` directory, and will append a unique hash to the filename, allowing for cache-busting. For example, the generated file name will look something like: `all-16d570a7.css`:

```javascript
elixir( function( mix ){
    mix.version( 'css/all.css' );
} );
```

## Versioning Multiple Files

You may pass an array to the `version` method to version multiple files:

```javascript
elixir( function( mix ){
    mix.version( [ 'css/all.css', 'js/app.js' ] );
} );
```

## Custom Output Directory

By default the `version` task will create a `build` folder in your `includes` folder that will contain a revision json file and the versioned assets according to `js` or `css` type. You can change the destination using the second argument:

```javascript
elixir( function( mix ){
    mix.version( [ 'css/all.css', 'js/app.js' ], "includes/versioned" );
} );
```


# ColdBox Helper Methods

ColdBox v4.3.0 has two methods in the HTML Helper object: `elixir() and elixirPath()` to specifically help with versioned assets exclusively.

However, you can leverage versioned assets in any version of ColdBox by adding the following methods to your ColdBox Application Helper or Views Helper file that is set in your application's `ColdBox.cfc`. Please note that these methods are identical to the one in ColdBox v4.3.0:

```javascript
<cfscript>
    /**
    * Adds the versioned path for an asset to the view
    * @filename The asset path to find relative to the includes convention directory
    * @buildDirectory The build directory inside the includes convention directory
    * @sendToHeader Send to the header via htmlhead by default, else it returns the content
    * @async HTML5 JavaScript argument: Specifies that the script is executed asynchronously (only for external scripts)
    * @defer HTML5 JavaScript argument: Specifies that the script is executed when the page has finished parsing (only for external scripts)
    */
    function elixir(
        required filename,
        buildDirectory="build",
        boolean sendToHeader=true,
        boolean async=false,
        boolean defer=false
    ){
        html.addAsset(
            elixirPath( arguments.fileName, arguments.buildDirectory ),
            arguments.sendToHeader,
            arguments.async,
            arguments.defer
        );

        return this;
    }

    /**
    * Finds the versioned path for an asset if leveraging ColdBox Elixir
    * @returns The path
    */
    string function elixirPath( required string fileName, buildDirectory="build" ){
        var includesConvention     = "includes";
        var mapping             = event.getCurrentModule() != "" ? event.getModuleRoot() : controller.getSetting( "appMapping" );
        var filePath             = expandPath( "#mapping#/#includesConvention#/#arguments.buildDirectory#/rev-manifest.json" );
        var href                 = "#mapping#/#includesConvention#/#arguments.fileName#";

        if ( ! fileExists( filePath ) ) {
            return href;
        }

        var fileContents = fileRead( filePath );
        if ( ! isJSON( fileContents ) ) {
            return href;
        }

        var json = deserializeJSON( fileContents );
        if ( ! structKeyExists( json, arguments.fileName ) ) {
            return href;
        }

        return "#mapping#/#includesConvention#/#arguments.buildDirectory#/#json[ arguments.fileName ]#";
    }
</cfscript>
```

You can then just use them in your layouts or views to include versioned files:

```markup
<head>
  #elixir( "css/myapp.css" )#
</head>
<body>
   ...

  #elixir( "js/app.js" )#
</body>
```


# Mixing in tasks from ColdBox Modules

ColdBox Modules can be an excellent way to structure your project, and ColdBox Elixir is the perfect companion. Use all the Elixir methods you know and love in your modules, and Elixir will build them all for you with just one command.

```javascript
elixir( function( mix ){
    mix.modules();
});
```

## `elixir-module.js`

To specify what Elixir functions to run, a module needs to define an `elixir-module.js` file. This file looks very similar to a `gulpfile`. Here is an example of one:

```javascript
module.exports = function( mix ){
    mix.sass( "app.scss" );
};
```

The function here is exactly the same function you would write inside the `elixir` call in your main `gulpfile`. Every method installed in your main `gulpfile` is available here. The one **important** difference is that this function must be exported so that Elixir can pick it up and add it to the build steps.

Elixir will scope the changes to the current module's directory. This means, for example, that:

```javascript
mix.sass( "app.scss" )
```

Inside of a module with a path `/modules_app/my-module/elixir-module.js` will look for an `app.scss` file inside of `/modules_app/my-module/resources/assets/sass/app.scss` and compile it to `/modules_app/my-module/includes/css/app.css`.

Watch mode works exactly as you would expect — modules add their scoped mixes to the watch tasks just like every other Elixir task.

## Running a Single Module

You can compile a single module's assets by using `mix.module()` passing in the module's name:

```javascript
// /gulpfile.js
elixir( function( mix ){
    mix.module( "my-module" );
});
```

This will look for the following file: `/modules_app/my-module/elixir-module.js` and add the resulting mix function to the gulp tasks. If the file does not exist or is not a function, Elixir will show an error and continue on with the other build tasks.

You can pass more than file in by using an array for the first parameter:

```javascript
// /gulpfile.js
elixir( function( mix ){
    mix.module( [ "my-module", "my-second-module" ] );
});
```

The second and third parameters change the conventions and should be used less frequently.

```javascript
// /gulpfile.js
elixir( function( mix ){
    mix.module( "my-module", "new_base_directory", "new-filename.js" );
});
```

This would look in `/new_base_direectory/my-module/new-filename.js` for the mix function.

## Running a folder of modules

There is a shortcut to build all compatible modules in with Elixir:

```javascript
elixir( function( mix ){
    mix.modules();
});
```

You can call this function with no arguments. It will find all modules in the default base modules directory (`/modules_app`) with the default filename (`elixir-module.js`) and add their tasks to the build.

You can further customize this function by passing in an array of includes directories as the first argument.

```javascript
elixir( function( mix ){
    mix.modules( [ "modules_app", "lib/modules" ] );
});
```

This will mix all compatible modules in both directories.

Also, you can pass an array of exclude module names as the second parameter. These modules (if they exist in the source directories) will be ignored.

```javascript
elixir( function( mix ){
    mix.modules(
        null, /* passing null uses the default of /modules_app */
        [ "my-old-fashioned-module" ]
    );
});
```

Explicitly ignoring modules doesn't need to be done often since modules missing the mix filename (`elixir-module.js` by default) are ignored when calling `mix.modules()`

Finally, the mix filename can be overridden as the third argument:

```javascript
elixir( function( mix ){
    mix.modules(
        null, /* passing null here uses the default of /modules_app */
        null, /* passing null here uses the defeault of [] */
        "mixfile.js"
    );
});
```

But this is a lot of work for really no benefit, so just stick to the conventions, yeah?


# Copying Files & Directories

The `copy` method may be used to copy files and/or directories to new locations. All operations are relative to the project's `root` directory:

```javascript
elixir( function( mix ){
    mix.copy( 'resources/vendor/foo/bar.css', 'includes/css/bar.css' );
} );

elixir( function( mix ){
    mix.copy( 'vendor/package/views', 'views' );
} );
```

> **Tip**: The first argument can be a file or folder path or an array of paths. You can also use any globbing patterns.


# Deleting Files & Directories

You might want to delete some files before, during or after running your build. Since deleting files doesn't work on the file contents, there's no reason to use a gulp plugin within Elixir. You can use the [`del`](https://github.com/sindresorhus/del) module which is included in ColdBox Elixir and it supports multiple files and [globbing](https://github.com/sindresorhus/multimatch#globbing-patterns):

Imagine the following file structure:

```
.
├── dist
│   ├── report.csv
│   ├── desktop
│   └── mobile
│       ├── app.js
│       ├── deploy.json
│       └── index.html
└── src
```

In the gulpfile we want to clean out the contents of the `mobile` folder before running our build:

```javascript
var del     = require( 'del' );
var elixir     = require( 'coldbox-elixir' );

elixir( function( mix ){

    del( [
        'dist/report.csv',
        // here we use a globbing pattern to match everything inside the `mobile` folder
        'dist/mobile/**/*',
        // we don't want to clean this file though so we negate the pattern
        '!dist/mobile/deploy.json'
    ] );

} );
```


# Executing Command Line Binaries

You may use the `exec()` method to execute any command line shell script. Just pass a normal string that will be evaluated by the shell of the Operating System you are on. Like CommandBox integration for example!

```javascript
elixir( function( mix ){
    mix.exec( "box testbox run" );
} );
```

## Attaching Watchers

You can also attach a watcher to the command execution. Let's say you want all the Tests to execute if there are any changes to them:

```javascript
elixir( function( mix ){
    mix.exec( "box testbox run", "tests/**/*.cfc" );
} );
```


# Calling Gulp Tasks

If you need to call an existing Gulp task from Elixir, you may use the `task` method. As an example, imagine that you have a Gulp task that simply speaks a bit of text when called:

```
gulp.task( 'speak', function() {
    var message = 'Tea...Earl Grey...Hot';

    gulp.src( '' ).pipe( shell( 'say ' + message ) );
});
```

If you wish to call the `speak` task from Elixir, use the `mix.task` method and pass the `name` of the task as the only argument to the method:

```javascript
elixir( function( mix ){
    mix.task( 'speak' );
});
```

## Custom Watchers

If you need to register a watcher to run your custom task each time some files are modified, pass a regular expression as the second argument to the `task` method:

```
elixir( function( mix ){
    mix.task( 'speak', 'tests/**/*.cfc' );
});
```


# Custom Watchers

If you would like your custom task to be re-triggered while running `gulp watch`, you may register a watcher:

```javascript
new Task( 'speak', function(){
    return gulp.src( '' ).pipe( shell( 'say ' + message ) );
})
.watch( './app/**' );
```


# BrowserSync

[BrowserSync](https://www.browsersync.io/) automatically refreshes your web browser after you make changes to your front-end resources. You can use the `browserSync` method to instruct Elixir to start a BrowserSync server when you run the `gulp watch` command:

```javascript
elixir( function( mix ){
    mix.browserSync();
});
```

After running this command you will see directions to add a script tag to the bottom of your website like this:

```bash
[BS] Copy the following snippet into your website, just before the closing </body> tag
<script id="__bs_script__">//<![CDATA[
    document.write("<script async src='http://HOST:3000/browser-sync/browser-sync-client.2.12.5.js'><\/script>".replace("HOST", location.hostname));
//]]></script>
```

Add that snippet to your `layouts/Main.cfm` file and reload to enable BrowserSync!

## Specifying a Proxy

Instead of copying the script tag into you app, you can tell BrowserSync to proxy your existing CFML server:

```
elixir( function( mix ){
    mix.browserSync( {
        proxy : 'localhost:50608'
    } );
} );
```

Running `gulp watch` will now open up `localhost:3000` which proxies to your app! No need for that BrowserSync script tag anymore!

## Custom Options

In addition to the `proxy` option, you may pass any BrowserSync option here as the first argument. A list of the BrowserSync options can be found [here](http://www.browsersync.io/docs/options/).


# Vue.js Integration

ColdBox Elixir has an optional installation package to provide you with [Vue.js](https://github.com/ortus-docs/elixir-docs/tree/ab2f68d1fd39bedfca5b2a86f84126acd069e92d/vuejs.org) and [Vueify component](https://github.com/vuejs/vueify) compilation out of the box. This will allow you to create `.vue` extension components, integrate with Vue.js and Browserify will compile them for you.

You will begin by installing Vue.js via npm: `npm install vue --save`. This will add `Vue` as a dependency for your project in your project's `package.json` and into the `node_modules` directory. The following is the `package.json` you should use when integrating with Vue.js:

**package.json**

```javascript
{
  "private": true,
  "devDependencies": {
    "coldbox-elixir": "1.1.0",
    "gulp": "^3.9.1"
  },
  "dependencies": {
    "vue": "^2.0.0"
  }
}
```

Then create your normal JavaScript and Vue components in your `resources/assets/js` folder. You can even use the new (EcmaScript6)\[<https://babeljs.io/docs/learn-es2015/>] syntax if you like, then just mix them up using the `webpack`, `rollup`, or `browserify` method:

**Gulpfile.js**

```javascript
var elixir = require( "coldbox-elixir" );


elixir( function( mix ){
    mix.webpack( "app.js" );
});
```

Your `App.js` can look like this:

**resources/assets/js/App.js**

```javascript
import Vue from 'vue';

new Vue({
  el: '#app',
  data: {
    message: "Hello, world!"
  }
});
```

And you can import any components following the same relative path of the `resources/assets/js` folder.

You can also use the optional `.vue` syntax which allows you to co-locate your template, styles, and scripts. Read more about the `.vue` syntax [here](https://github.com/vuejs/vueify).

**resources/assets/js/App.js**

```javascript
import Vue from 'vue';
import Profile from './components/Profile.vue';

new Vue({
  el: '#app',
  components: { Profile }
});
```

To use this syntax, you will need the [`coldbox-elixir-vue`](https://github.com/coldbox-elixir/extension-vue) or [`coldbox-elixir-vue-2`](https://github.com/coldbox-elixir/extension-vue-2) extension, depending on which version of Vue.js you are running. See the individual GitHub pages for installation instructions.

**resources/assets/js/components/Profile.vue**

```
<template>
  <div class="profile">
    {{ name }}
  </div>
</template>

<script>
export default {
  data () {
    return {
      name: 'Luis Majano'
    };
  }
};
</script>

<style>
.profile {
    background: #eee;
    border: 1px solid #aaa;
    border-radius: 2em;
    margin: 2em auto;
    min-height: 150px;
    padding: 2em;
    width: 300px;
}
</style>
```

You would then use this in your ColdBox layout or view like so:

```markup
<div id="app">
    <profile></profile>
</div>
<script src="/includes/js/App.js"></script>
```


# Writing Elixir Extensions

> **Tip:** Looking at the code for the official ColdBox Elixir extensions will help immensely as you begin writing your own extensions. You can find them in the at [ColdBox Elixir](https://github.com/coldbox-elixir) GitHub organization prefixed with `extension-`.

If you need more flexibility than Elixir's `task` method can provide, you may create custom Elixir extensions. Elixir extensions allow you to pass arguments to your custom tasks. For example, you could write an extension like so:

```javascript
// File: elixir-extensions.js

var gulp     = require( 'gulp' );
var shell     = require( 'gulp-shell' );
var elixir    = require( 'coldbox-elixir' );

var Task = elixir.Task;

elixir.extend( 'speak', function( message ){

    new Task( 'speak', function(){
        return gulp.src( '' ).pipe( shell( 'say ' + message ) );
    });

});

// Then we can call it
mix.speak( 'Hello World' );
```

That's it! Notice that your Gulp-specific logic should be placed within the function passed as the second argument to the `Task` constructor. You may either place this at the top of your Gulpfile, or instead extract it to a custom tasks file. For example, if you place your extensions in `elixir-extensions.js`, you may require the file from your main Gulpfile like so:

```
// File: Gulpfile.js

var elixir = require( 'coldbox-elixir' );

require( './elixir-extensions' )

elixir( function( mix ){
    mix.speak( 'Tea, Earl Grey, Hot' );
});
```


# Introduction

![Elixir Logo](https://3913911445-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LA-UVvDWU72L1kpFjM1%2F-Lo5jlJ0VgLLobaOUmQN%2F-Lo5jmEGWYZpnbaO6DH1%2FelixirLogo300.png?generation=1567776254289270\&alt=media)

ColdBox Elixir provides a clean, fluent API for defining basic [Webpack](http://webpack.js.org/) tasks for your ColdBox applications.

## Versioning

ColdBox Elixir is maintained under the [Semantic Versioning](http://semver.org) guidelines as much as possible. Releases will be numbered with the following format:

```
<major>.<minor>.<patch>
```

And constructed with the following guidelines:

* Breaking backward compatibility bumps the major (and resets the minor and patch)
* New additions without breaking backward compatibility bumps the minor (and resets the patch)
* Bug fixes and misc changes bumps the patch

## License

MIT License: <https://opensource.org/licenses/MIT>.

## Important Links

* Code: <http://github.com/ortus-solutions/coldbox-elixir>
* Issues: <https://ortussolutions.atlassian.net/secure/RapidBoard.jspa?projectKey=ELIXIR>
* Documentation: <http://coldbox-elixir.ortusbooks.com>

## Professional Open Source

![Ortus Solutions, Corp](https://3913911445-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LA-UVvDWU72L1kpFjM1%2F-Lo5jlJ0VgLLobaOUmQN%2F-Lo5jmEI97CI1Xdo9RCp%2Fortussolutions_button.png?generation=1567776254140283\&alt=media)

ColdBox Elixir is a professional open source software backed by [Ortus Solutions, Corp](http://www.ortussolutions.com/services) offering services like:

* Custom Development
* Professional Support & Mentoring
* Training
* Server Tuning
* Security Hardening
* Code Reviews
* [Much More](http://www.ortussolutions.com/services)

### HONOR GOES TO GOD ABOVE ALL

Because of His grace, this project exists. If you don't like this, then don't read it, it's not for you.

> "Therefore being justified by **faith**, we have peace with God through our Lord Jesus Christ: By whom also we have access by **faith** into this **grace** wherein we stand, and rejoice in hope of the glory of God." Romans 5:5


# Changelog

## 3.0.0

* **Major upgrade** to ColdBox Elixir.  No longer mirroring Laravel Elixir.
* All compilation is done through Webpack instead of Gulp.
* Removed the following methods:
  * `mix.less`
  * `mix.stylus`,
  * `mix.scripts`
  * `mix.scriptsIn`
  * `mix.webpack`
  * `mix.browserify`,
  * `mix.rollup`
  * `mix.version`
  * `mix.exec`
  * `mix.task`
* The entire Elixir configuration object has changed.  See [Configuration Options](/master-3/configuration_options) for details.
* PostCSS support is now automatic if a `postcss.config.js` file is found in the project root.
* The `elixir` and `elixirPath` helper functions in ColdBox 5.0.0 and earlier are incompatible with ColdBox Elixir 3.0.0.  Please see the [Versioning docs](/master-3/versioning) for updated helper functions.

## 2.0.0

* Updated to stay current with Laravel Elixir 6.0.0.
* Deprecated `mix.babel()` in favor of `mix.browserify()`, `mix.webpack`, `mix.rollup`, or similar module bundlers.
* Nicer console output.
* Broke out first party extensions from the core (to keep in line with Laravel Elixir 6.0.0)
  * [`coldbox-elixir-browserify`](https://github.com/coldbox-elixir/extension-browserify)
  * [`coldbox-elixir-browsersync`](https://github.com/coldbox-elixir/extension-browsersync)
  * [`coldbox-elixir-rollup`](https://github.com/coldbox-elixir/extension-rollup)
  * [`coldbox-elixir-stylus`](https://github.com/coldbox-elixir/extension-stylus)
  * [`coldbox-elixir-vue`](https://github.com/coldbox-elixir/extension-vue)
  * [`coldbox-elixir-webpack`](https://github.com/coldbox-elixir/extension-webpack)
* Helpful warnings when trying to use methods provided by a first party extension.

## 1.1.0

* Travis Support
* BDD via TestBox fixes
* Updated all dependencies to latest versions
* Gulp tasks for compilation, tests and watchers
* Test App additions for testing direct gulp integrations
* If not tasks defined in the user's gulpfile, just a message is shown instead of an exception
* Removed coffeescript support, no longer needed
* Added new config map for `appPaths` to support all ColdBox conventions
* Vueify core support view browserify for Vue.js components
* Included a new `template` folder which helps setting up new elixir based projects

## 1.0.0

* Initial Port to ColdBox


# Migration Guide

If you used a previous version of ColdBox Elixir a lot has changed. This guide will step you through the changes.

## Dependencies

ColdBox Elixir no longer requires `gulp`. You can uninstall it.

ColdBox Elixir will install all necessary dependencies when installing or updating it from NPM. There are other dependencies which may be installed on-demand once as you use them.

## Running Elixir

Since ColdBox Elixir doesn't use `gulp` any more, we need to make some changes to our `gulpfile.js`.

1. Rename `gulpfile.js` to `webpack.config.js`.
2. Export the result of `elixir()`

```javascript
// webpack.config.js
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    // ....
});
```

1. (Optional) Create some NPM scripts to make build commands easier to remember. This let's us run `npm run dev` or `npm run watch` to build our project.

```javascript
{
    "scripts": {
        "dev": "webpack",
        "watch": "npm run dev -- --watch",
        "build": "npm run dev -- -p"
    }
}
```

## Asset Names

Due to the way Webpack processes css files, you can no longer have a css file named `vendor`.

## Tasks

The following tasks have been removed from ColdBox Elixir.

* `mix.less`
* `mix.combine`
* `mix.browserify`
* `mix.rollup`
* `mix.exec`

If you rely on any of these methods you can either stay with ColdBox Elixir v2 or you can [recreate the task yourself.](/master-3/writing_elixir_extensions)

## Method Changes

### `mix.styles`

`mix.styles` should be replaced with `mix.css`.

The method signature for `mix.css` is has changed.

| Name                    | Type   | Required | Default                                        | Description                                                                      |
| ----------------------- | ------ | -------- | ---------------------------------------------- | -------------------------------------------------------------------------------- |
| filename                | String | `true`   |                                                | The filename to bundle.                                                          |
| options                 | Object | `false`  | (see below)                                    | An object for additional options. Any missing keys will use their default value. |
| options.name            | String | `false`  | The name of the filename without the extension | The name of the outputed bundle                                                  |
| options.outputDirectory | String | `false`  | `includes/css`                                 | The output directory for the built file.                                         |
| options.entryDirectory  | String | `false`  | `resources/assets/css/`                        | The directory where the filename is located.                                     |

### `mix.scripts`

`mix.scripts` should be replaced with [`mix.js`](/master-3/working_with_scripts). `mix.js` will automatically run the code through Babel. Babel is preconfigured with `babel-preset-env`, but it can be customized by specifying your own `.babelrc` file in the root of your project. See the [Babel docs](https://babeljs.io/docs/en/babelrc) for more information.

The method signature for `mix.scripts` has changed.

| Name                    | Type   | Required | Default                                        | Description                                                                      |
| ----------------------- | ------ | -------- | ---------------------------------------------- | -------------------------------------------------------------------------------- |
| filename                | String | `true`   |                                                | The filename to bundle.                                                          |
| options                 | Object | `false`  | (see below)                                    | An object for additional options. Any missing keys will use their default value. |
| options.name            | String | `false`  | The name of the filename without the extension | The name of the outputed bundle                                                  |
| options.outputDirectory | String | `false`  | `includes/js`                                  | The output directory for the built file.                                         |
| options.entryDirectory  | String | `false`  | `resources/assets/js/`                         | The directory where the filename is located.                                     |

### `mix.webpack`

`mix.webpack` should be replaced with either [`mix.js`](/master-3/working_with_scripts) or [`mix.vue`](/master-3/vuejs_integration) depending on your use case. `mix.vue` includes some extra dependencies and configuration to process `.vue` files while `mix.js` will just process your files through Babel.

The method signature for `mix.js` and `mix.vue` are the same.

| Name                    | Type   | Required | Default                                        | Description                                                                      |
| ----------------------- | ------ | -------- | ---------------------------------------------- | -------------------------------------------------------------------------------- |
| filename                | String | `true`   |                                                | The filename to bundle.                                                          |
| options                 | Object | `false`  | (see below)                                    | An object for additional options. Any missing keys will use their default value. |
| options.name            | String | `false`  | The name of the filename without the extension | The name of the outputed bundle                                                  |
| options.outputDirectory | String | `false`  | `includes/js`                                  | The output directory for the built file.                                         |
| options.entryDirectory  | String | `false`  | `resources/assets/js/`                         | The directory where the filename is located.                                     |

### `mix.sass`

The method signature for `mix.sass` has changed.

| Name                    | Type   | Required | Default                                        | Description                                                                      |
| ----------------------- | ------ | -------- | ---------------------------------------------- | -------------------------------------------------------------------------------- |
| filename                | String | `true`   |                                                | The filename to bundle.                                                          |
| options                 | Object | `false`  | (see below)                                    | An object for additional options. Any missing keys will use their default value. |
| options.name            | String | `false`  | The name of the filename without the extension | The name of the outputed bundle                                                  |
| options.outputDirectory | String | `false`  | `includes/css`                                 | The output directory for the built file.                                         |
| options.entryDirectory  | String | `false`  | `resources/assets/sass/`                       | The directory where the filename is located.                                     |

### `mix.version`

Versioning is now the default for a production build (`webpack -p`). You can also control if the files are versioned by setting the `elixir.versioning` config property in your `webpack.config.js` file.

### `mix.stylesIn` and `mix.scriptsIn`

These methods should be replaced with individual calls to `mix.css` and `mix.js`.

## Extensions

Extensions that were made for ColdBox Elixir v2 are not compatible with v3. See [*Writing Elixir Extensions*](/master-3/writing_elixir_extensions) for more information on how to create v3 compatible extensions.

## Elixir Config File

The Elixir config file has changed completely. The available configuration options are available in [*Configuration Options.*](/master-3/configuration_options)


# Installation

## Installing Node

Before triggering Elixir, you must first ensure that [Node.js](https://nodejs.org/en/) is installed on your machine. You will want at least the latest LTS version of Node.

```
node -v
```

## Installing ColdBox Elixir

If you generate a ColdBox application using any of our [elixir templates](https://github.com/coldbox-templates/) then you will find a `package.json` file in the root of the application already. Think of this like your `box.json` file, except it defines Node dependencies instead of ColdFusion (CFML) dependencies. A typical example can look like this:

```js
{
  "private": true,
  "devDependencies": {
    "coldbox-elixir": "^4.0.1"
  }
}
```

It defines ColdBox Elixir as a dev dependency. You may then install the dependencies it references by running:

```
npm install
```

This will install ColdBox Elixir and its dependencies into the `node_modules` folder in your root. This folder has been already added to the `.gitignore` file as well, so no need to further ignore it.


# Running Elixir

Elixir is built on top of Webpack, so to run your Elixir tasks you only need to run the `webpack` command in your terminal. Before running Webpack, you will need a `webpack.config.js` file in the root of your project. Below is a simple example:

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.js("app.js");
});
```

Please note that by adding the `-p` flag to the command will turn on Webpack's production mode. This will minify your CSS and JavaScript files as well as add long-term caching hashes to your compiled files.

## Watching Assets For Changes

For performance and convienence, you can run Webpack in watch mode by passing the `-w` or `--watch` flag. Any changes to your source files will automatically re-run your build. Note that your build will be significantly faster on subsequent changes than when running Webpack from scratch.

## NPM Scripts

The easiest way to run Webpack is to set up some NPM scripts. Here are the following we recommend:

```javascript
"scripts": {
    "dev": "webpack --hide-modules",
    "watch": "npm run dev -- --watch",
    "prod": "npm run dev -- -p"
}
```

Then from the terminal you can run `npm run [scriptName]` to run the associated script.


# Configuration Options

All of Elixir's configuration is to support Webpack. Most of the custom changes you will make to Elixir will come through the `mergeConfig` method.

```javascript
const elixir = require("coldbox-elixir");

elixir.config.mergeConfig({});
```

The `mergeConfig` method will intelligently merge your new config with the existing Webpack config (thanks to [`webpack-merge`](https://github.com/survivejs/webpack-merge)).

There are a few additional config options on the Elixir object.

* `elixir.isProduction`
  * By default checks for the production flag from the terminal (`-p`)
* `elixir.rootPath`
  * The root of the project
* `elixir.config`
  * A configured instance of `ElixirConfig`
* `elixir.versioning`
  * Defaults to `elixir.isProduction`


# Working With Stylesheets

## Working With Stylesheets

Elixir processes all CSS files through Webpack. This brings with it some nifty Webpack properties such as [automatic url resolution](https://github.com/webpack-contrib/css-loader).

## CSS

> Due to the way Webpack processes css files, you can no longer have a css file named `vendor`.

You can mix traditional css with webpack using `mix.css`. You can pass one file or an array of files.

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.css("app.css");
    mix.css([
        "node_modules/normalizecss/normalize.css"
        "resources/assets/css/normalize_overrides.css"
    ], {
        name: "normalize.css",
        entryDirectory: ""
    });
});
```

`mix.css` accepts a configuration object as the second parameter:

```javascript
{
    name: this.withoutExtension(filename),
    outputDirectory: "includes/css/",
    entryDirectory: "resources/assets/css/"
}
```

## PostCSS

If you add a `postcss.config.js` file to the root of your project, Elixir will process all of your styles through PostCSS. To learn more about PostCSS, visit [their documentation](https://postcss.org/).

## Sass

The `sass` method allows you to compile [Sass](http://sass-lang.com/) into CSS. Assuming your Sass files are stored at `resources/assets/sass`, you may use the method like so:

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.sass("app.scss");
});
```

Like the `css` method you may compile multiple Sass files into a single CSS file, and even customize the output directory of the resulting CSS:

```
elixir( function( mix ){
    mix.sass([
        "app.scss",
        "controllers.scss"
    ], {
        outputDirectory: "public/assets/css"
    });
} );
```

## Other Pre-processors

Elixir can be extended with any other pre-processor you would like. See our docs on [writing your own extensions](/master-3/writing_elixir_extensions) for others!


# Working With Scripts

You can compile scripts using the `mix.js` method. It accepts either a single file or an array of files to combine. Each file will be crawled for dependencies by Webpack.

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.js("app.js");
    mix.js([
        "node_modules/jquery/dist/jquery.min.js",
        "node_modules/bootstrap-sass/assets/javascripts/bootstrap.min.js"
    ], {
        name: "vendor",
        entryDirectory: ""
    });
});
```

The second argument to `mix.js` is a configuration object.

```javascript
{
    name: this.withoutExtension(filename),
    outputDirectory: "includes/js/",
    entryDirectory: "resources/assets/js/"
}
```


# Versioning Cache Busting

By default, Elixir will version all your compiled assets when compiling for production `webpack -p`.

This produces a file with a unique hash in the filename. This hash will only change if the contents of the file change.

You can change or turn off the versioning by setting the `elixir.versioning` property in your `webpack.config.js` file.

Additionally, Elixir will generate an `/includes/manifest.json` file. This file maps the original file name to the hashed file name. This lets you still use the original file name in your code and not have to update your templates whenever your assets change.

ColdBox (5.1+) ships with some helper methods for this purpose. You can also copy the code below for use in your own projects.

```javascript
<cfscript>
    /**
    * Adds the versioned path for an asset to the view
    * @filename The asset path to find relative to the includes convention directory
    * @buildDirectory The build directory inside the includes convention directory
    * @sendToHeader Send to the header via htmlhead by default, else it returns the content
    * @async HTML5 JavaScript argument: Specifies that the script is executed asynchronously (only for external scripts)
    * @defer HTML5 JavaScript argument: Specifies that the script is executed when the page has finished parsing (only for external scripts)
    */
    function elixir(
        required filename,
        boolean sendToHeader=true,
        boolean async=false,
        boolean defer=false
    ){
        html.addAsset(
            elixirPath( arguments.fileName ),
            arguments.sendToHeader,
            arguments.async,
            arguments.defer
        );

        return this;
    }

    /**
    * Finds the versioned path for an asset if leveraging ColdBox Elixir
    * @returns The path
    */
    string function elixirPath( required string fileName ){
        var includesConvention     = "includes";
        var mapping             = event.getCurrentModule() != "" ? event.getModuleRoot() : controller.getSetting( "appMapping" );
        var filePath             = expandPath( "#mapping#/#includesConvention#/manifest.json" );
        var href                 = "#mapping#/#includesConvention#/#arguments.fileName#";

        if ( ! fileExists( filePath ) ) {
            return href;
        }

        var fileContents = fileRead( filePath );
        if ( ! isJSON( fileContents ) ) {
            return href;
        }

        var json = deserializeJSON( fileContents );
        if ( ! structKeyExists( json, arguments.fileName ) ) {
            return href;
        }

        return "#mapping#/#includesConvention#/#json[ arguments.fileName ]#";
    }
</cfscript>
```

You can then just use them in your layouts or views to include versioned files:

```markup
<head>
    #elixir( "css/myapp.css" )#
</head>
<body>
    <!-- ... -->

    <script src="#elixirPath( "js/app.js" )#"></script>
</body>
```


# Mixing in tasks from ColdBox Modules

ColdBox Modules can be an excellent way to structure your project, and ColdBox Elixir is the perfect companion. Use all the Elixir methods you know and love in your modules, and Elixir will build them all for you with just one command.

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.modules();
});
```

## `elixir-module.js`

To specify what Elixir functions to run a module needs to define an `elixir-module.js` file. This file looks very similar to your `webpack.config.js`. Here is an example of one:

```javascript
module.exports = mix => {
    mix.sass("app.scss");
};
```

The function here is exactly the same function you would write inside the `elixir` call in your main `webpack.config.js` file. Every method installed in your main `webpack.config.js` file is available here.

Elixir will scope the changes to the current module's directory. This means, for example, that:

```javascript
mix.sass("app.scss");
```

Inside of a module with a path `/modules_app/my-module/elixir-module.js` will look for an `app.scss` file inside of `/modules_app/my-module/resources/assets/sass/app.scss` and compile it to `/modules_app/my-module/includes/css/app.css`.

### Includes, Excludes, and File name

You can specify and array of folders to include, folders to exclude, or change the default file name if you wish:

| Argument   | Default Value      |
| ---------- | ------------------ |
| `includes` | `["modules_app"]`  |
| `excludes` | `[]`               |
| `fileName` | `elixir-module.js` |

## Running a Single Module

You can compile a single module's assets by using `mix.module()` passing in the module's name:

```javascript
// /gulpfile.js
elixir(mix => {
    mix.module("my-module");
});
```

This will look for the following file: `/modules_app/my-module/elixir-module.js` and add the resulting mix function to the gulp tasks. If the file does not exist or is not a function, Elixir will show an error and continue on with the other build tasks.

The second parameter is a configuration object to change the folderName or fileName to look for:

```javascript
elixir(mix => {
    mix.module("my-module", {
        folderName: "new_base_directory",
        fileName: "new-filename.js"
    });
});
```

This would look in `/new_base_directory/my-module/new-filename.js` for the mix function.


# ContentBox Integration

ColdBox Elixir has a few helper methods when working in a ContentBox app.

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.themes();
    mix.contentbox();
});
```

These two methods work just like a call to `mix.modules` with some different defaults set.

> For a refresher on how `mix.modules` and `elixir-module.js` files work, see the [modules docs.](/master-3/coldbox_modules)

## `mix.themes`

This method will look inside the `modules_app/contentbox-custom/_themes` directory for any folders with a `elixir-theme.js` file. The `elixir-theme.js` file is identical to a `elixir-module.js` file.

## `mix.contentbox`

This method will look inside the `modules_app/contentbox-custom/_modules` directory for any folders with a `elixir-module.js` file.


# Copying Files & Directories

The `copy` method may be used to copy files and/or directories to new locations. All operations are relative to the project's `root` directory:

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.copy("resources/vendor/foo/bar.css", "includes/css/bar.css");
});
```


# Deleting Files & Directories

By default the following directories are cleaned out for each build:

```
"includes/js"
"includes/css"
"includes/fonts"
"includes/media"
"includes/images"
```

If you would like to add additional directories, you can do so by configuring a new instance of the `CleanWebpackPlugin`:

```javascript
const elixir = require("coldbox-elixir");
const CleanWebpackPlugin = require("clean-webpack-plugin");

elixir.config.mergeConfig({
    plugins: [
        new CleanWebpackPlugin(["my/custom/directory"], { root: elixir.rootPath })
    ]
});
```


# BrowserSync

[BrowserSync](https://www.browsersync.io/) automatically refreshes your web browser after you make changes to your front-end resources. You can use the `browserSync` method to instruct Elixir to start a BrowserSync server when you run the `gulp watch` command:

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.browserSync();
});
```

After running this command you will see directions to add a script tag to the bottom of your website like this:

```bash
[BS] Copy the following snippet into your website, just before the closing </body> tag
<script id="__bs_script__">//<![CDATA[
    document.write("<script async src='http://HOST:3000/browser-sync/browser-sync-client.2.12.5.js'></script>".replace("HOST", location.hostname));
//]]></script>
```

Add that snippet to your `layouts/Main.cfm` file and reload to enable BrowserSync!

## Specifying a Proxy

Instead of copying the script tag into you app, you can tell BrowserSync to proxy your existing CFML server:

```javascript
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.browserSync({
        proxy: "localhost:50608"
    });
});
```

Running `webpack -w` will now open up `localhost:3000` which proxies to your app! No need for that BrowserSync script tag anymore!

## Default Options

We define a number of default options for BrowserSync:

```javascript
{
    host: "localhost",
    port: 3000,
    proxy: "http://localhost:8888",
    files: "**/*"
}
```

The can be overridden by passing in an options object as the only parameter (as seen above with `proxy`).

## Custom Options

In addition to the `proxy` option, you may pass any BrowserSync option here as the only argument. A list of the BrowserSync options can be found [here](http://www.browsersync.io/docs/options/).


# Vue.js Integration

ColdBox Elixir lets you work with `.vue` files out of the box.

You will begin by installing Vue.js via npm: `npm install vue`. This will add `Vue` as a dependency for your project in your project's `package.json` and into the `node_modules` directory. The following is the `package.json` you should use when integrating with Vue.js:

**package.json**

```js
{
  "private": true,
  "devDependencies": {
    "coldbox-elixir": "3.0.0",
  },
  "dependencies": {
    "vue": "^2.0.0"
  }
}
```

Then create your normal JavaScript and Vue components in your `resources/assets/js` folder.

```js
const elixir = require("coldbox-elixir");

module.exports = elixir(mix => {
    mix.vue("app.js");
});
```

`mix.vue` accepts a configuration object as the second parameter which has the following defaults:

```js
{
    name: this.withoutExtension(filename),
    outputDirectory: "includes/js/",
    entryDirectory: "resources/assets/js/"
}
```

Your `App.js` can look like this:

**resources/assets/js/App.js**

```js
import Vue from "vue";

new Vue({
  el: "#app",
  data: {
    message: "Hello, world!"
  }
});
```

And you can import any components following the same relative path of the `resources/assets/js` folder.

You can also use the optional `.vue` syntax which allows you to co-locate your template, styles, and scripts in a single-file component.

**resources/assets/js/App.js**

```js
import Vue from "vue";
import Profile from "./components/Profile.vue";

new Vue({
  el: "#app",
  components: { Profile }
});
```

**resources/assets/js/components/Profile.vue**

```
<template>
  <div class="profile">
    {{ name }}
  </div>
</template>

<script>
export default {
  data () {
    return {
      name: "Luis Majano"
    };
  }
};
</script>

<style>
.profile {
    background: #eee;
    border: 1px solid #aaa;
    border-radius: 2em;
    margin: 2em auto;
    min-height: 150px;
    padding: 2em;
    width: 300px;
}
</style>
```

You would then use this in your ColdBox layout or view like so:

```html
<div id="app">
	<profile></profile>
</div>
<script src="/includes/js/App.js"></script>
```

Any style blocks in your `.vue` components will be extracted as well to the same directory as your javascript file as a css file. For example, if you were compiling `mix.vue( "app.js" )` Elixir would generate a `includes/js/app.css` file containing the css for the style blocks used in that entrypoint.

> Note: there are some drawbacks with style blocks in Vue components and Elixir. if you are creating multiple entry points with multiple `mix.vue` calls, any style blocks in shared components will be duplicated in each of the css files. Additionally, because Elixir is already extracting other css files, style blocks in Vue components are always extracted. For these reasons, we recommend using other approaches to managing your css with Vue components and Elixir.


# Writing Elixir Extensions

## `mergeConfig`

Occasionally you will need to extend Webpack in ways not supported by ColdBox Elixir. In these moments, you can provide your own configuration using the `mergeConfig` method.

```javascript
const elixir = require("coldbox-elixir");

elixir.config.mergeConfig({
    // custom webpack config goes here
});
```

The `mergeConfig` method will merge the object provided with the existing Webpack config using the excellent [`webpack-merge` library](https://github.com/survivejs/webpack-merge).

## Custom Ingredients

Ingredients are the name for the methods available on the `mix` object. You can add an ingredient to your Elixir instance like so:

```javascript
const elixir = require("coldbox-elixir");

elixir.config.addIngredient("nameOfIngredient", () => {
    // function to run when called (mix.nameOfIngredient());
    // any parameters passed to the `mix.nameOfIngredient()` call will be available in the function.
    // The `this` scope refers to the ElixirConfig object, so methods like `this.mergeConfig` are available.
})
```

The main use cases for using an ingredient over custom config are:

1. Need to call multiple times each time for different file(s)
2. Want to re-use across projects

Especially in the second case, feel free to publish the ingredient on NPM if you feel it could be useful to other developers.


