Skip to content
Ryan Christian edited this page Aug 13, 2022 · 24 revisions

Some common recipes for use in preact.config.js

See Webpack Config Helpers for reference on helpers argument.

Customising babel options (using loader helpers)

To customize babel config babel-loader options have to be changed.

/**
 * @param {import('preact-cli').Config} config - Original webpack config
 * @param {import('preact-cli').Env} env - Current environment info
 * @param {import('preact-cli').Helpers} helpers - Object with useful helpers for working with the webpack config
 */
export default (config, env, helpers) => {
  let { rule } = helpers.getLoadersByName(config, 'babel-loader')[0];
  let babelConfig = rule.options;
  
  babelConfig.plugins.push(require.resolve('my-chosen-plugin'));
  babelConfig.env = { 
    // ...some settings... 
  }
};

Disabling source maps (using plugin helpers)

/**
 * @param {import('preact-cli').Config} config - Original webpack config
 * @param {import('preact-cli').Env} env - Current environment info
 * @param {import('preact-cli').Helpers} helpers - Object with useful helpers for working with the webpack config
 */
export default (config, env, helpers) => {
  if (env.isProd) {
    config.devtool = false;
  }
}

Conditional changes based on env

/**
 * @param {import('preact-cli').Config} config - Original webpack config
 * @param {import('preact-cli').Env} env - Current environment info
 * @param {import('preact-cli').Helpers} helpers - Object with useful helpers for working with the webpack config
 */
export default (config, env, helpers) => {
  if (env.isServer) {
    // ...do something for prerender...
  } else {
    // ...do something for regular bundles...
  }

  if (env.isProd) {
    // ...do something for production...
  } else {
    // ...do something for watch mode...
  }
}

Setting proxy for dev server (using config directly)

/**
 * @param {import('preact-cli').Config} config - Original webpack config
 * @param {import('preact-cli').Env} env - Current environment info
 * @param {import('preact-cli').Helpers} helpers - Object with useful helpers for working with the webpack config
 */
export default (config, env, helpers) => {
  // devServer doesn't exist on production builds
  if (!env.isProd) {
    config.devServer.proxy = [
      {
        path: '/api/**',
        target: 'http://api.example.com',
        // ...any other stuff...
      }
    ];
  }
}

Removing plugin, loader or rule

Each wrapper for plugin, loader or rule comes with it's position in array so that it can be easily removed.

/**
 * @param {import('preact-cli').Config} config - Original webpack config
 * @param {import('preact-cli').Env} env - Current environment info
 * @param {import('preact-cli').Helpers} helpers - Object with useful helpers for working with the webpack config
 */
export default (config, env, helpers) => {
  let { index } = helpers.getPluginsByName(config, 'some-plugin')[0]
  config.plugins.splice(index, 1)
};

Merge static assets with the /build folder

This config will take all files (not folders) at the root of /src/assets and copy them into the build folder (configurable using --dest). This means, /src/assets/robots.txt will be copied to /build/robots.txt and thus will be available at www.example.com/robots.txt.

First: npm install copy-webpack-plugin@^6.0.0

import CopyWebpackPlugin from 'copy-webpack-plugin';
import { resolve } from 'path';

/**
 * @param {import('preact-cli').Config} config - Original webpack config
 * @param {import('preact-cli').Env} env - Current environment info
 * @param {import('preact-cli').Helpers} helpers - Object with useful helpers for working with the webpack config
 */
export default (config, env, helpers) => {
    config.plugins.push(
        new CopyWebpackPlugin({
            patterns: [{
                from: '*',
                context: resolve(__dirname, 'src/assets')
            }],
        }),
    );
}

See also https://github.com/preactjs/preact-cli/issues/436#issuecomment-650964073.

Absolute Imports

It can sometimes be undesirable to use relative imports when you have a deeply nested directory structure, e.g., import ... from '../../../components/App.js';. To make this easier, you may want to use absolute imports. These are the most common ways to use absolute imports; which you choose depends on personal preference:

  1. import ... from 'src/components/App.js';

    import { join } from 'path';
    
    /**
     * @param {import('preact-cli').Config} config - Original webpack config
     * @param {import('preact-cli').Env} env - Current environment info
     * @param {import('preact-cli').Helpers} helpers - Object with useful helpers for working with the webpack config
     */
    export default (config, env, helpers) => {
        config.resolve.alias.src = join(process.cwd(), 'src');
    }
  2. import ... from 'components/App.js';

    import { join } from 'path';
    
    /**
     * @param {import('preact-cli').Config} config - Original webpack config
     * @param {import('preact-cli').Env} env - Current environment info
     * @param {import('preact-cli').Helpers} helpers - Object with useful helpers for working with the webpack config
     */
    export default (config, env, helpers) => {
        config.resolve.modules.push(join(process.cwd(), 'src'));
    }

Use environment variables in your application

If you'd like to reference and use environment variables in your application, you will need to use DefinePlugin.

/**
 * @param {import('preact-cli').Config} config - Original webpack config
 * @param {import('preact-cli').Env} env - Current environment info
 * @param {import('preact-cli').Helpers} helpers - Object with useful helpers for working with the webpack config
 */
export default (config, env, helpers) => {
    const { plugin } = helpers.getPluginsByName(config, 'DefinePlugin')[0];
    plugin.definitions['process.env.MY_VARIABLE'] = JSON.stringify('my-value');
}

This will replace every usage of process.env.MY_VARIABLE in your code with 'my-value'.