1import { basename } from 'path';
2import commonjs from 'rollup-plugin-commonjs';
3import nodeResolve from 'rollup-plugin-node-resolve';
4import buble from 'rollup-plugin-buble';
5import babel from 'rollup-plugin-babel';
6import { terser } from 'rollup-plugin-terser';
7import compiler from '@ampproject/rollup-plugin-closure-compiler';
8
9const pkgInfo = require('./package.json');
10const { main, peerDependencies, dependencies } = pkgInfo;
11const name = basename(main, '.js');
12
13let external = ['dns', 'fs', 'path', 'url'];
14if (pkgInfo.peerDependencies) external.push(...Object.keys(peerDependencies));
15if (pkgInfo.dependencies) external.push(...Object.keys(dependencies));
16
17const externalPredicate = new RegExp(`^(${external.join('|')})($|/)`);
18const externalTest = id => externalPredicate.test(id);
19
20const terserPretty = terser({
21 sourcemap: true,
22 warnings: true,
23 ecma: 5,
24 keep_fnames: true,
25 ie8: false,
26 compress: {
27 pure_getters: true,
28 toplevel: true,
29 booleans_as_integers: false,
30 keep_fnames: true,
31 keep_fargs: true,
32 if_return: false,
33 ie8: false,
34 sequences: false,
35 loops: false,
36 conditionals: false,
37 join_vars: false
38 },
39 mangle: false,
40 output: {
41 beautify: true,
42 braces: true,
43 indent_level: 2
44 }
45});
46
47const terserMinified = terser({
48 sourcemap: true,
49 warnings: true,
50 ecma: 5,
51 ie8: false,
52 toplevel: true,
53 mangle: true,
54 compress: {
55 keep_infinity: true,
56 pure_getters: true,
57 passes: 10
58 },
59 output: {
60 comments: false
61 }
62});
63
64// This plugin finds state that BuckleScript has compiled to array expressions
65// and unwraps them and their accessors to inline variables
66const unwrapStatePlugin = ({ types: t }) => ({
67 pre() {
68 this.props = new Map();
69 },
70 visitor: {
71 VariableDeclarator(path) {
72 if (t.isIdentifier(path.node.id) && t.isArrayExpression(path.node.init)) {
73 const id = path.node.id.name;
74 const elements = path.node.init.elements;
75 const decl = elements.map((element, i) => {
76 const key = `${id}$${i}`;
77 return t.variableDeclarator(t.identifier(key), element);
78 });
79
80 this.props.set(id, elements.length);
81 path.parentPath.replaceWithMultiple(t.variableDeclaration('let', decl));
82 }
83 },
84 MemberExpression(path) {
85 if (
86 t.isIdentifier(path.node.object) &&
87 this.props.has(path.node.object.name) &&
88 t.isNumericLiteral(path.node.property) &&
89 path.node.property.value < this.props.get(path.node.object.name)
90 ) {
91 const id = path.node.object.name;
92 const elementIndex = path.node.property.value;
93 path.replaceWith(t.identifier(`${id}$${elementIndex}`));
94 }
95 }
96 }
97});
98
99const makePlugins = isProduction =>
100 [
101 nodeResolve({
102 mainFields: ['module', 'jsnext', 'main'],
103 browser: true
104 }),
105 commonjs({
106 ignoreGlobal: true,
107 include: /\/node_modules\//
108 }),
109 buble({
110 transforms: {
111 unicodeRegExp: false,
112 dangerousForOf: true,
113 dangerousTaggedTemplateString: true
114 },
115 objectAssign: 'Object.assign',
116 exclude: 'node_modules/**'
117 }),
118 babel({
119 babelrc: false,
120 exclude: 'node_modules/**',
121 presets: [],
122 plugins: ['babel-plugin-closure-elimination', unwrapStatePlugin]
123 }),
124 compiler({
125 compilation_level: 'SIMPLE_OPTIMIZATIONS'
126 }),
127 isProduction ? terserMinified : terserPretty
128 ].filter(Boolean);
129
130const config = {
131 input: './src/index.js',
132 onwarn: () => {},
133 external: externalTest,
134 treeshake: {
135 propertyReadSideEffects: false
136 }
137};
138
139export default [
140 {
141 ...config,
142 plugins: makePlugins(false),
143 output: [
144 {
145 sourcemap: true,
146 legacy: true,
147 freeze: false,
148 esModule: false,
149 file: `./dist/${name}.js`,
150 format: 'cjs'
151 },
152 {
153 legacy: true,
154 freeze: false,
155 esModule: false,
156 file: `./dist/${name}.es.js`,
157 format: 'esm'
158 }
159 ]
160 },
161 {
162 ...config,
163 plugins: makePlugins(true),
164 output: [
165 {
166 legacy: true,
167 freeze: false,
168 esModule: false,
169 file: `./dist/${name}.min.js`,
170 format: 'cjs'
171 }
172 ]
173 }
174];