# Using your component library within other projects

If you want to include your Fractal component library as a dependency in another project, one way to do so is to package it up as an Node module and import it via NPM.

# 1. Prepare your library for publishing

To set up your library for publishing, you will need to:

  1. Make sure that the paths in your fractal.config.js are full contextual paths (i.e. making use of the Node __dirname global)
  2. Set a name for your component library in your package.json file - for instance foocorp-component-library.
  3. Set the value of the main (opens new window) field in your package.json to be fractal.config.js.
  4. Either publish to NPM as a module or push to Github. Full details of publishing and consuming NPM modules is outside the scope of these docs but there are plenty of good tutorials on the web.

# 2. Include in your project

In the project that you want to include the fractal component library in:

  1. Install fractal: npm i @frctl/fractal
  2. Install your component library: npm i foocorp-component-library
  3. Create a fractal.config.js file in the root of your project that looks as follows:
const fractal = module.exports = require('foocorp-component-library');

// any other custom, instance specific configuration here if needed

You should now be able to run fractal commands such as fractal start from within the parent project's root directory and they will operate on your component library as if it were part of the project itself.

# 3. Next steps

Obviously just including the component library into another project is not that useful by itself - you now need to decide how you want to consume that component library code in your project.

Generally you have a number of options, the primary ones being:

  1. Use the Fractal API to directly include and render components within your application (only applicable if you are building a Node.JS app)
  2. Write a bespoke template loader for your project that loads templates from your library, perhaps making use of a mapping of component handles -> paths that can be generated by Fractal.
  3. Export the templates from your library into your project, possibly with some path re-writing as part of the export process, and then consume these exported templates in your project as required.

For example, a bespoke Fractal CLI task for option 3 might look something like:

// setup/import etc...

const fs = require('fs');
const path = require('path');

/*
 * Fractal export command.
 *
 * Exports all view templates into a directory in the root of the project.
 * Templates are exported in a flat structure with the filenames in the format of {handle}.{ext}
 * Requires either an output directory that exists, or uses `exported` if it exists
 *
 * Any @handle references in the templates (for partial includes etc) are re-written
 * to reference the appropriate template path.
 *
 * Run by using the command `fractal export` in the root of the project directory.
 */
function exportTemplates(args, done) {

    const app = this.fractal;
    const items = app.components.flattenDeep().toArray();
    const jobs = [];

    for (const item of items) {

        const exportPath = path.join('./', args.options.output || 'exported', `${item.alias || item.handle}${app.get('components.ext')}`);
        const job = item.getContent().then(str => {
            return str.replace(/\@([0-9a-zA-Z\-\_]*)/g, function(match, handle){
                return `${handle}${app.get('components.ext')}`;
            });
        }).then(str => {
            return fs.writeFileSync(exportPath, str);
        });

        jobs.push(job);
    }

    return Promise.all(jobs);
}

fractal.cli.command('export', exportTemplates,  {
    description: 'Export all component templates',
    options: [
        ['-o, --output <output-dir>', 'The directory to export components into, relative to the CWD.'],
    ]
});