-
Notifications
You must be signed in to change notification settings - Fork 0
/
rollup.config.js
190 lines (171 loc) · 5.7 KB
/
rollup.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
import fs from 'fs';
import path from 'path';
import { babel } from '@rollup/plugin-babel';
import json from '@rollup/plugin-json';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import postcss from 'rollup-plugin-postcss';
import stringHash from 'string-hash';
import cssUrl from 'postcss-url';
const isDevelopment = process.env.NODE_ENV === 'development';
// Move our babel config into the root but use it to compile all of our packages
const getBabelOptions = ({
// This path has to be relative to our packages
babelConfigFile = '../../babel.config.js',
useESModules,
}) => ({
babelHelpers: 'runtime',
configFile: babelConfigFile,
exclude: '**/node_modules/**',
plugins: [['@babel/plugin-transform-runtime', { useESModules }]],
});
// Also making this a function since we may need to move some of the PostCSS config to the package root to be used in Cosmos or Doc tooling.
const getPostCSSOptions = () => ({
// extract: 'styles.css',
minimize: true,
modules: {
generateScopedName: function (name, filename, css) {
const path = require('path');
const [file] = path.basename(filename).split('.');
const hash = isDevelopment
? 'DEV_MODE'
: stringHash(css).toString(36).substr(0, 5);
return `☕️_${file}_${name}__${hash}`;
},
},
plugins: [cssUrl({ url: 'inline' })],
sourceMap: true,
use: [
'sass',
// [
// 'sass',
// {
// // includePaths: [path.resolve('../../node_modules/@espressive/')],
// importer: [
// (url, prev, done) => {
// // Convert `@use "foo/bar"` to "node_modules/foo/sass/bar".
// const components = url.split('/');
// const file = path.resolve('../../node_modules/', ...components);
// // console.log(file);
// done({
// // file: `node_modules/${components.first}/sass/${innerPath}`,
// file,
// });
// },
// ],
// },
// ],
],
});
const external = (id) =>
!id.startsWith('\0') && !id.startsWith('.') && !id.startsWith('/');
// Pragmatically create a Rollup config for each package
const getRollupConfig = ({ pwd, babelConfigFile }) => {
const SOURCE_DIR = path.resolve(pwd);
const PRIVATE_PATH = `${SOURCE_DIR}/src/private.js`;
// Get the package.json file
const pkgConfig = require(`${SOURCE_DIR}/package.json`);
// Relative input location for Rollup to bundle from
const input = [`${SOURCE_DIR}/src/index.js`];
// If we have a private export, add it to our list of inputs
if (fs.existsSync(PRIVATE_PATH)) {
input.push(PRIVATE_PATH);
}
// Shared Rollup plugins
const rollupPlugins = [nodeResolve(), postcss(getPostCSSOptions()), json()];
// separate out our bundle into chunks based on section for now
const manualChunks = (id) => {
const CHUNK_SECTIONS = fs
// Check our source directory
.readdirSync(`${SOURCE_DIR}/src`, {
withFileTypes: true,
})
// Remove anything except directories https://nodejs.org/api/fs.html#class-fsdirent
.filter((dirent) => dirent.isDirectory())
// Get anything in these directories and use a flat map to merge all returned
// arrays to a single array. This is not recursive, so depth from src is only 2.
.flatMap(({ name: subDir }) => {
const filePath = path.join(SOURCE_DIR, 'src', subDir);
return (
fs
// Get the file types again
.readdirSync(filePath, {
withFileTypes: true,
})
// Filter directories again
.filter(
(dirent) =>
dirent.isDirectory() &&
// Check to make sure the first character is uppercase
dirent.name.charAt(0) === dirent.name.charAt(0).toUpperCase()
)
// Return the subdir and name for the segment chunk
.map(({ name }) => `${subDir}/${name}`)
);
});
for (const segment of CHUNK_SECTIONS) {
if (id.startsWith(`${SOURCE_DIR}/src/${segment}`)) {
return segment;
}
}
if (id.includes('node_modules')) {
return 'vendor';
}
return undefined;
};
// Common JS configuration
const cjsConfig = {
external,
input,
output: {
// We use the directory defined in the package.json to determine the output location
// instead of hard coding a path to output our files.
dir: `${SOURCE_DIR}/${pkgConfig.main.replace('/index.js', '')}`,
// Even though the default for `export` here is 'auto' we for some reason need to explicitly define it for cjs with a default vs named export
exports: 'auto',
format: 'cjs',
manualChunks,
sourcemap: true,
sourcemapExcludeSources: true,
validate: true,
},
plugins: [
babel(
getBabelOptions({
babelConfigFile,
useESModules: false,
})
),
...rollupPlugins,
],
};
const pkgConfigModule = pkgConfig ? pkgConfig.module || '' : '';
// Modules configuration
const esConfig = {
external,
input,
output: {
// We use the directory defined in the package.json to determine the output location
// instead of hard coding a path to output our files.
dir: `${SOURCE_DIR}/${pkgConfigModule.replace('/index.js', '')}`,
format: 'es',
manualChunks,
sourcemap: true,
sourcemapExcludeSources: true,
validate: true,
},
plugins: [
babel(
getBabelOptions({
babelConfigFile,
useESModules: true,
})
),
...rollupPlugins,
],
};
if (process.env.WATCH_MODE) {
return [cjsConfig, esConfig];
}
return [cjsConfig, esConfig];
};
export default getRollupConfig;