Created
July 28, 2021 12:37
-
-
Save krisanalfa/e17ce5cb2b633e6a706811d7ecef8a0f to your computer and use it in GitHub Desktop.
Simple Webpack Plugin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { rollup } from 'rollup' | |
import { babel } from '@rollup/plugin-babel' | |
import nodeResolve from '@rollup/plugin-node-resolve' | |
import commonjs from '@rollup/plugin-commonjs' | |
import { terser } from 'rollup-plugin-terser' | |
import replace from '@rollup/plugin-replace' | |
import { Compiler, compilation } from 'webpack' | |
import { Tapable } from 'tapable' | |
export class RollupPlugin implements Tapable.Plugin { | |
constructor( | |
private readonly options: { | |
/** | |
* Input of the file you want to transpile. | |
*/ | |
input: string | |
/** | |
* The destination of transpiled file (relative to webpack output path). | |
*/ | |
destination: string | |
/** | |
* The returning object must be: | |
* ```ts | |
* interface Replacer { | |
* [keyInProcessEnv: string]: string | |
* } | |
* ``` | |
* | |
* This object will be used to replace strings in our bundle | |
* (utilised by `@rollup/plugin-replace` plugin). | |
* The value of the object is the default value when the | |
* value of `process.env[keyInProcessEnv]` is falsy. For example: | |
* ```ts | |
* // Input | |
* { | |
* NODE_ENV: 'production' | |
* } | |
* | |
* // Output | |
* { | |
* 'process.env.NODE_ENV': process.env.NODE_ENV || 'production' | |
* } | |
* ``` | |
* | |
* The first param of the function is the instance of `NodeJS.ProcessEnv`, | |
* you can utilize this param if you want to get the value from other env. | |
* For example: | |
* ```ts | |
* // Input | |
* { | |
* replacer: (env) => ({ | |
* NODE_ENV: env.CI ? 'production' : 'development' | |
* }) | |
* } | |
* | |
* // Output | |
* { | |
* NODE_ENV: process.env.NODE_ENV | |
* || (process.env.CI ? 'production' : 'development') | |
* } | |
* ``` | |
* | |
*/ | |
replacer: (env: NodeJS.ProcessEnv) => Record<string, string> | |
} | |
) {} | |
public apply(compiler: Compiler) { | |
const { input, destination } = this.options | |
compiler.hooks.emit.tapPromise( | |
RollupPlugin.name, | |
async (compilation: compilation.Compilation) => { | |
try { | |
const bundle = await rollup({ | |
input, | |
plugins: [ | |
nodeResolve(), | |
replace({ | |
...this.normalizeReplacer(), | |
preventAssignment: true, | |
}), | |
commonjs(), | |
babel({ | |
babelHelpers: 'bundled', | |
babelrc: false, | |
configFile: false, | |
exclude: ['node_modules/**'], | |
presets: [['@babel/preset-env']], | |
}), | |
terser(), | |
], | |
}) | |
const { | |
output: [{ code }], | |
} = await bundle.generate({ | |
format: 'es', | |
}) | |
compilation.assets[destination] = { | |
source: () => code, | |
size: () => code.length, | |
} | |
} catch (error) { | |
compilation.errors.push(error) | |
} | |
} | |
) | |
} | |
private normalizeReplacer() { | |
const replacer = this.options.replacer(process.env) | |
return Object.keys(replacer).reduce( | |
(a, c) => ({ | |
...a, | |
[`process.env.${c}`]: JSON.stringify(process.env[c] || replacer[c]), | |
}), | |
<Record<string, string>>{} | |
) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment