Skip to content

Commit 6930472

Browse files
a bit hacky but home page is now being built for production
1 parent 1beeb5f commit 6930472

10 files changed

+203
-304
lines changed

packages/cli/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"access": "public"
2626
},
2727
"dependencies": {
28+
"@rollup/plugin-json": "^4.1.0",
2829
"@rollup/plugin-node-resolve": "^9.0.0",
2930
"@webcomponents/webcomponentsjs": "^2.4.4",
3031
"acorn": "^8.0.1",
@@ -42,6 +43,7 @@
4243
"remark-parse": "^8.0.3",
4344
"remark-rehype": "^7.0.0",
4445
"rollup": "^2.26.5",
46+
"rollup-plugin-ignore-import": "^1.3.2",
4547
"rollup-plugin-multi-input": "^1.1.1",
4648
"rollup-plugin-postcss": "^3.1.5",
4749
"rollup-plugin-terser": "^7.0.0",

packages/cli/src/commands/build.js

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const { execSync } = require('child_process');
12
const fs = require('fs');
23
const generateCompilation = require('../lifecycles/compile');
34
const serializeBuild = require('../lifecycles/serialize');
@@ -19,13 +20,16 @@ module.exports = runProductionBuild = async () => {
1920
}
2021

2122
await serializeBuild(compilation);
22-
23-
// // TODO rollup only understands ESM in Node :/
24-
// // rollup.write(rollupConfig);
25-
26-
// // 5) run rollup on .greenwood and put into public/
27-
// // TODO this is a hack just for the sake of the POC, will do for real :)
28-
// execSync('rollup -c ./rollup.config.js');
23+
24+
// TODO this is a hack just for the sake of the POC, will do for real :)
25+
// rollup.write(rollupConfig);
26+
execSync('rollup -c ./packages/cli/src/config/rollup.config.js');
27+
28+
// TODO part of rollup?
29+
execSync(`cp -vr ${compilation.context.userWorkspace}/assets/ ./public/assets`);
30+
31+
// TODO should be done by rollup
32+
execSync(`cp -vr ${compilation.context.userWorkspace}/styles/ ./public/styles`);
2933

3034
resolve();
3135
} catch (err) {
+5-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module.exports = {
2-
plugins: {
3-
'postcss-preset-env': {}, // stage 2+
4-
'postcss-nested': {},
5-
'cssnano': {}
6-
}
2+
// plugins: {
3+
// 'postcss-preset-env': {}, // stage 2+
4+
// 'postcss-nested': {},
5+
// 'cssnano': {}
6+
// }
77
};
+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
import fs from 'fs';
2+
import { promises as fsPromises } from 'fs';
3+
import htmlparser2 from 'htmlparser2';
4+
import json from '@rollup/plugin-json';
5+
import multiInput from 'rollup-plugin-multi-input';
6+
import { nodeResolve } from '@rollup/plugin-node-resolve';
7+
import path from 'path';
8+
import postcss from 'rollup-plugin-postcss';
9+
import { terser } from 'rollup-plugin-terser';
10+
import ignoreImport from 'rollup-plugin-ignore-import';
11+
12+
const scratchDirectory = path.join(process.cwd(), '.greenwood');
13+
const workspaceDirectory = path.join(process.cwd(), 'www');
14+
const outputDirectory = path.join(process.cwd(), 'public');
15+
16+
function greenwoodWorkspaceResolver () {
17+
return {
18+
name: 'greenwood-workspace-resolver', // this name will show up in warnings and errors
19+
resolveId(source) {
20+
// TODO better way to handle relative paths? happens in generateBundle too
21+
if ((source.indexOf('./') === 0 || source.indexOf('/') === 0) && path.extname(source) !== '.html' && fs.existsSync(path.join(workspaceDirectory, source))) {
22+
const resolvedPath = source.replace(source, path.join(workspaceDirectory, source));
23+
// console.debug('resolve THIS sauce to workspace directory, returning ', resolvedPath);
24+
25+
return resolvedPath; // this signals that rollup should not ask other plugins or check the file system to find this id
26+
}
27+
28+
return null; // other ids should be handled as usually
29+
}
30+
};
31+
}
32+
33+
// https://github.com/rollup/rollup/issues/2873
34+
function greenwoodHtmlPlugin() {
35+
36+
return {
37+
name: 'greenwood-html-plugin',
38+
load(id) {
39+
if (path.extname(id) === '.html') {
40+
return '';
41+
}
42+
},
43+
// TODO do this during load instead?
44+
async buildStart(options) {
45+
// TODO dont emit duplicate scripts, e.g. use a Map()
46+
const that = this;
47+
const parser = new htmlparser2.Parser({
48+
onopentag(name, attribs) {
49+
if (name === 'script' && attribs.type === 'module' && attribs.src) {
50+
// TODO handle deeper paths
51+
const srcPath = attribs.src.replace('../', './');
52+
const scriptSrc = fs.readFileSync(path.join(workspaceDirectory, srcPath), 'utf-8');
53+
54+
that.emitFile({
55+
type: 'chunk',
56+
id: srcPath,
57+
name: srcPath.split('/')[srcPath.split('/').length - 1].replace('.js', ''),
58+
source: scriptSrc
59+
});
60+
61+
// console.debug('emitFile for script => ', srcPath);
62+
}
63+
}
64+
});
65+
66+
for (const input in options.input) {
67+
const inputHtml = options.input[input];
68+
const html = await fsPromises.readFile(inputHtml, 'utf-8');
69+
70+
parser.write(html);
71+
parser.end();
72+
parser.reset();
73+
}
74+
},
75+
async generateBundle(outputOptions, bundles) {
76+
const mappedBundles = new Map();
77+
78+
// TODO looping over bundles twice is wildly inneficient, should refactor and safe references once
79+
for (const bundleId of Object.keys(bundles)) {
80+
const bundle = bundles[bundleId];
81+
82+
// TODO handle (!) Generated empty chunks .greenwood/about, .greenwood/index
83+
if (bundle.isEntry && path.extname(bundle.facadeModuleId) === '.html') {
84+
const html = await fsPromises.readFile(bundle.facadeModuleId, 'utf-8');
85+
let newHtml = html;
86+
87+
const parser = new htmlparser2.Parser({
88+
onopentag(name, attribs) {
89+
if (name === 'script' && attribs.type === 'module' && attribs.src) {
90+
// console.debug('bundle', bundle);
91+
// console.debug(bundles[innerBundleId])
92+
for (const innerBundleId of Object.keys(bundles)) {
93+
const facadeModuleId = bundles[innerBundleId].facadeModuleId;
94+
const pathToMatch = attribs.src.replace('../', '').replace('./', '');
95+
96+
if (facadeModuleId && facadeModuleId.indexOf(pathToMatch) > 0) {
97+
// console.debug('MATCH FOUND!!!!!!!');
98+
newHtml = newHtml.replace(attribs.src, `/${innerBundleId}`);
99+
} else {
100+
// console.debug('NO MATCH?????', innerBundleId);
101+
// TODO better testing
102+
if(innerBundleId.indexOf('.greenwood/') < 0 && !mappedBundles.get(innerBundleId)){
103+
// console.debug('NEW BUNDLE TO INJECT!');
104+
newHtml = newHtml.replace(/<script type="module" src="(.*)"><\/script>/, `
105+
<script type="module" src="/${innerBundleId}"></script>
106+
`);
107+
mappedBundles.set(innerBundleId, true);
108+
}
109+
}
110+
}
111+
}
112+
}
113+
});
114+
115+
parser.write(html);
116+
parser.end();
117+
118+
// TODO this seems hacky :D
119+
bundle.fileName = bundle.facadeModuleId.replace('.greenwood', './public');
120+
bundle.code = newHtml;
121+
}
122+
}
123+
}
124+
};
125+
}
126+
127+
export default [{
128+
// TODO Avoid .greenwood/ directory, do everything in public/?
129+
input: `${scratchDirectory}/**/*.html`,
130+
output: {
131+
dir: outputDirectory,
132+
entryFileNames: '[name].[hash].js',
133+
chunkFileNames: '[name].[hash].js'
134+
},
135+
plugins: [
136+
// ignoreImport({
137+
// include: ['**/*.css'],
138+
// // extensions: ['.css']
139+
// }),
140+
nodeResolve(),
141+
greenwoodWorkspaceResolver(),
142+
greenwoodHtmlPlugin(),
143+
multiInput(),
144+
postcss({
145+
extract: false,
146+
minimize: true
147+
}),
148+
json(), // TODO bundle as part of import support?
149+
terser()
150+
]
151+
// }, {
152+
// input: `${workspaceDirectory}/**/*.css`, // TODO emits a www/styles.js file?
153+
// output: { // TODO CSS filename hashing / cache busting - https://github.com/egoist/rollup-plugin-postcss/pull/226
154+
// dir: outputDirectory
155+
// },
156+
// plugins: [
157+
// multiInput(),
158+
// postcss({
159+
// extract: true,
160+
// minimize: true
161+
// })
162+
// ]
163+
}];

packages/cli/src/config/webpack.config.common.js

-172
This file was deleted.

0 commit comments

Comments
 (0)