Skip to content

kaysonwu/babel-plugin-preprocessor

Repository files navigation

Preprocessor Directives

An babel plugin for transform preprocessor directives

npm Node Downloads License Build Status

English | 中文

Installation

yarn add -D babel-plugin-preprocessor

or

npm install -D babel-plugin-preprocessor

Options

interface PluginOptions {
  symbols: Record<string, any>;
  directives: Record<string, boolean>;
}

Set plugin options in babel configuration file:

{
  "plugins": [
    ...
    ["preprocessor", {
      "symbols": { "IS_BROWSER": true },
      "directives": { "DEBUG": true }
    }]
  ]
}

Usage

Build-in Directives

Before using #if / #else / #elseif (alias: #elif) / #endif build-in Directives, you need to configure the symbols option in the babel configuration file.

// #if IS_BROWSER
console.log('This is browser');
// #else
console.log('It\\'s unknown');
// #endif

If IS_BROWSER is truthy, console.log ('It\\'s unknown'); will be deleted and vice versa.

Complex use case

Use the symbols parameter like variable:

{
  "plugins": [
    ["preprocessor", { "symbols": { "IE": 8, "UA": "Chrome" } }]
  ]
}
// #if (IE > 8 && IE < 12) || UA.startsWith('Chrome')
console.log('Support HTML5');
// #else
console.log('HTML5 is not supported'); // This line will be deleted
// #endif

Custom Directives

By configuring the directives option to implement custom directives:

// #debug
console.log('debug message');

If debug is falsy, console.log will be deleted.

Note that the custom directive only affects its next line, which means:

// #debug
console.log('debug message'); // This line will be omitted
const a = ''; // This line will be retained

This plugin is inspired by webpack-preprocessor-loader, Therefore, you can safely use its built-in directives:

// #!if IS_BROWSER
console.log('This is browser');
// #!else
console.log('It\\'s unknown');
// #!endifWW

If you use its #!debug directive, please configure directives option, If you also use its verbose option, then you need to configure the symbols option according to the usage.

Typescript

To suppress the error, a tricky way is simply adding // @ts-ignore before all declarations:

// #if ENV = 'develop'
// @ts-ignore
const foo = 1;
// #else
// @ts-ignore
const foo = -1;
// #endif

JSX

Since version 0.0.2, JSX directives have been fully supported:

import React from 'react';
import ErrorBoundary from './boundary';

export default () => {
  return (
    /* #if IS_BROWSER */
    <ErrorBoundary fallback={() => <div>Fallback</div>}>
    {/* #endif */}
      <div>
        {/* #debug */}
        <span>This line should be deleted</span>
        Do something
      </div>
    {/* #if IS_BROWSER */} 
    </ErrorBoundary>
    /* #endif */  
  );
}

If a JSX element has a close tag, the directive to close the tag can be omitted:

import React from 'react';
import ErrorBoundary from './boundary';

export default () => {
  return (
    /* #if IS_BROWSER */
    <ErrorBoundary fallback={() => <div>Fallback</div>}>
    {/* #endif */}
      <div>
        {/* #debug */}
        <span>This line should be deleted</span>
        Do something
      </div>
    </ErrorBoundary>
  );
}

However, I suggest you keep it so that it is compatible with webpack-preprocessor-loader

Pay attention to the wrapping of elements when using JSX, otherwise there will be some unexpected results:

import React from 'react';
import ErrorBoundary from './boundary';

export default () => {
  return (
    /* #if IS_BROWSER */
    <ErrorBoundary fallback={() => <div>Fallback</div>}>
    {/* #endif */}
      {/* #debug */}
      <span>This line should be deleted</span>
      Do something
    {/* #if IS_BROWSER */} 
    </ErrorBoundary>
    /* #endif */  
  );
}

If IS_BROWSER is false and debug is true, then Do something line will be discarded.