Skip to content

Instantly share code, notes, and snippets.

@asimonok
Created June 28, 2022 11:15
Show Gist options
  • Save asimonok/f75f90a0084198fb2835374a5b86205c to your computer and use it in GitHub Desktop.
Save asimonok/f75f90a0084198fb2835374a5b86205c to your computer and use it in GitHub Desktop.
/*
** Copyright (c) 2020 Oracle and/or its affiliates.
*/
const fs = require('fs');
const path = require('path');
const {alias, manifest} = require('@oracle-cx-commerce/rollup-config/plugins');
const {babel} = require('@rollup/plugin-babel');
const builtins = require('builtin-modules');
const commonjs = require('@rollup/plugin-commonjs');
const json = require('@rollup/plugin-json');
const postCss = require('rollup-plugin-postcss');
const postCssImport = require('postcss-import');
const {nodeResolve} = require('@rollup/plugin-node-resolve');
const postcssCustomProperties = require('postcss-custom-properties');
const replace = require('@rollup/plugin-replace');
const {terser} = require('rollup-plugin-terser');
const typescriptPlugin = require('@rollup/plugin-typescript');
const omt = require('@surma/rollup-plugin-off-main-thread');
const {___} = require('@oracle-cx-commerce/tools-i18n').i18n({directory: path.join(__dirname, './locales')});
const loader = fs.readFileSync(path.join(__dirname, '/loader.ejs'), 'utf8');
const defaultExternals = [
'prop-types',
'react-docgen',
'react',
'react-dom',
'react-dom/server',
'node-fetch',
'http-proxy-agent',
'https-proxy-agent',
'@oracle-cx-commerce/logger',
'@oracle-cx-commerce/http-client',
...builtins
];
/*
Create and return an object containing all build configurations.
*/
const createBuildConfigs = (options = {}) => {
// Don't overwrite passed-in options.
options = {...options};
// Provide defaults for some options.
const {cssCustomPropertySources = require.resolve('@oracle-cx-commerce/styles/theme.css'), extraExternals = []} =
options;
// Use BUILD env var to allow production build to be specified
// unless it's explicitly included in options.
if (!('production' in options)) {
options.production = process.env.BUILD === 'production';
}
// Allow app dir to be explicitly specified in options or using the
// OCC_APP_DIR env var, which must be a path relative to the workspace root.
let {__dirname} = options;
if (!__dirname) {
const appDir = process.env.OCC_APP_DIR;
if (appDir) {
__dirname = `${process.cwd()}/${appDir}`;
}
}
// Validate app dir.
if (!__dirname) {
throw new Error(___`'__dirname' must be specified in options or using OCC_APP_DIR environment variable`);
}
if (!fs.existsSync(__dirname)) {
throw new Error(___`__dirname ${__dirname} does not exist`);
}
if (!fs.statSync(__dirname).isDirectory()) {
throw new Error(___`__dirname ${__dirname} is not a directory`);
}
const pkg = require(`${__dirname}/package.json`);
/* package.json meta data */
const {occ = {}} = pkg;
const {aliases = {}, external: pkgExternal = [], typescript = false} = occ;
// Combine default and provided externals.
const external = [...defaultExternals, ...extraExternals, ...pkgExternal];
/* common options start */
const input = {
client: 'src/client.js',
server: 'src/server.js'
};
const output = {
freeze: false,
sourcemap: true,
strict: false,
exports: 'auto'
};
/* plugin options */
const commonjsOptions = {
include: 'node_modules/**',
exclude: ['node_modules/@oracle-cx-commerce/**']
};
const jsonOptions = {
namedExports: false
};
const nodeResolveOptions = {
client: {
browser: true,
extensions: ['.ts', '.tsx', '.mjs', '.js', '.jsx', '.json', '.node']
},
server: {
extensions: ['.ts', '.tsx', '.mjs', '.js', '.jsx', '.json', '.node']
}
};
const typescriptOptions = {
allowSyntheticDefaultImports: true
};
const replaceOptions = {
dev: {
preventAssignment: true,
values: {
__ENABLE_USER_TIMING_API__: true,
__OCC_DEV__: true,
'process.env.NODE_ENV': '"development"'
}
},
prod: {
preventAssignment: true,
values: {
__ENABLE_USER_TIMING_API__: false,
__OCC_DEV__: false,
'process.env.NODE_ENV': '"production"'
}
}
};
const postCssOptions = {
dev: {
inject: true,
plugins: [
postCssImport(),
postcssCustomProperties({
importFrom: cssCustomPropertySources
})
]
},
prod: {
inject: true,
plugins: [
postCssImport(),
postcssCustomProperties({
importFrom: cssCustomPropertySources
})
],
minimize: true
}
};
const babelOptions = {
modern: {
extensions: ['.ts', '.tsx', '.js', '.jsx', '.es6', '.es', '.mjs'],
exclude: 'node_modules/react*/**',
babelHelpers: 'bundled'
},
legacy: {
extensions: ['.ts', '.tsx', '.js', '.jsx', '.es6', '.es', '.mjs'],
exclude: 'node_modules/react*/**',
babelHelpers: 'bundled',
presets: [
[
'@babel/env',
{
targets: {
browsers: ['ie >= 11']
},
loose: true,
modules: false
}
]
],
plugins: [
['@babel/plugin-proposal-class-properties', {loose: false}],
['@babel/plugin-proposal-private-methods', {loose: false}],
'@babel/plugin-syntax-dynamic-import',
[
'@babel/plugin-proposal-object-rest-spread',
{
useBuiltIns: true
}
],
[
'@babel/plugin-transform-regenerator',
{
async: false
}
],
[
'babel-plugin-transform-async-to-promises',
{
inlineHelpers: true,
externalHelpers: true
}
],
[
'@babel/plugin-transform-react-jsx',
{
useBuiltIns: true
}
],
[
'@babel/plugin-transform-destructuring',
{
useBuiltIns: true
}
]
]
}
};
const terserOptions = {
ecma: 8,
compress: {
/* eslint-disable camelcase */
keep_infinity: true,
drop_console: true,
pure_getters: true,
/* eslint-enable camelcase */
passes: 1
},
warnings: true
};
const masterConfig = {
clientLegacy: {
dev: {
input: [`${__dirname}/${input.client}`],
output: [
{
dir: `${__dirname}/dist/amd`,
format: 'amd',
entryFileNames: '[name]-[hash].js',
chunkFileNames: '[name]-[hash].js',
...output
}
],
preserveEntrySignatures: false,
plugins: [
alias(aliases),
nodeResolve(nodeResolveOptions.client),
typescript ? typescriptPlugin(typescriptOptions) : undefined,
replace(replaceOptions.dev),
commonjs(commonjsOptions),
json(jsonOptions),
postCss(postCssOptions.dev),
manifest({
publicPath: `${__dirname}/dist/amd`
}),
babel(babelOptions.legacy),
omt({
loader
})
],
context: 'self'
},
prod: {
input: [`${__dirname}/${input.client}`],
output: [
{
dir: `${__dirname}/dist/amd/min`,
format: 'amd',
entryFileNames: '[name]-[hash].js',
chunkFileNames: '[name]-[hash].js',
...output
}
],
preserveEntrySignatures: false,
plugins: [
alias(aliases),
nodeResolve(nodeResolveOptions.client),
typescript ? typescriptPlugin(typescriptOptions) : undefined,
replace(replaceOptions.prod),
commonjs(commonjsOptions),
json(jsonOptions),
postCss(postCssOptions.prod),
manifest({
publicPath: `${__dirname}/dist/amd/min`
}),
babel(babelOptions.legacy),
omt({
loader
}),
terser(terserOptions)
],
context: 'self'
}
},
clientModern: {
dev: {
input: [`${__dirname}/${input.client}`],
output: [
{
dir: `${__dirname}/dist/esm`,
format: 'esm',
entryFileNames: '[name]-[hash].js',
chunkFileNames: '[name]-[hash].js',
...output
}
],
preserveEntrySignatures: false,
plugins: [
alias(aliases),
nodeResolve(nodeResolveOptions.client),
typescript ? typescriptPlugin(typescriptOptions) : undefined,
replace(replaceOptions.dev),
commonjs(commonjsOptions),
json(jsonOptions),
postCss(postCssOptions.dev),
manifest({
publicPath: `${__dirname}/dist/esm`
}),
babel(babelOptions.modern)
]
},
prod: {
input: [`${__dirname}/${input.client}`],
output: [
{
dir: `${__dirname}/dist/esm/min`,
format: 'esm',
entryFileNames: '[name]-[hash].js',
chunkFileNames: '[name]-[hash].js',
...output
}
],
preserveEntrySignatures: false,
plugins: [
alias(aliases),
nodeResolve(nodeResolveOptions.client),
typescript ? typescriptPlugin(typescriptOptions) : undefined,
replace(replaceOptions.prod),
commonjs(commonjsOptions),
json(jsonOptions),
postCss(postCssOptions.prod),
manifest({
publicPath: `${__dirname}/dist/esm/min`
}),
babel(babelOptions.modern),
terser(terserOptions)
]
}
},
// config for development (non minified) server bundles
server: {
dev: {
input: [`${__dirname}/${input.server}`],
output: [
{
dir: `${__dirname}/dist/cjs`,
format: 'cjs',
...output
}
],
inlineDynamicImports: true,
external,
plugins: [
alias(aliases),
nodeResolve(nodeResolveOptions.server),
typescript ? typescriptPlugin(typescriptOptions) : undefined,
replace(replaceOptions.dev),
json(jsonOptions),
postCss(postCssOptions.dev),
manifest({
publicPath: `${__dirname}/dist/cjs`
}),
babel(babelOptions.modern)
]
},
prod: {
input: [`${__dirname}/${input.server}`],
output: [
{
dir: `${__dirname}/dist/cjs/min`,
format: 'cjs',
...output
}
],
inlineDynamicImports: true,
external,
plugins: [
alias(aliases),
nodeResolve(nodeResolveOptions.server),
typescript ? typescriptPlugin(typescriptOptions) : undefined,
replace(replaceOptions.prod),
json(jsonOptions),
postCss(postCssOptions.prod),
manifest({
publicPath: `${__dirname}/dist/cjs/min`
}),
babel(babelOptions.modern),
terser(terserOptions)
]
}
}
};
const configs = [];
configs.push(masterConfig.server.dev);
configs.push(masterConfig.clientModern.dev);
if (options.production || options.legacy || process.env.OCC_ADD_LEGACY_ROLLUP_CONF) {
configs.push(masterConfig.clientLegacy.dev);
}
if (options.production) {
configs.push(masterConfig.server.prod);
configs.push(masterConfig.clientModern.prod);
configs.push(masterConfig.clientLegacy.prod);
}
return configs;
};
module.exports = {
createBuildConfigs
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment