-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rfc/issue 185 resources refactor #466
Changes from all commits
2016aa4
55e6294
c0b51dc
7a138af
428e950
308b85c
f9723eb
e59da4a
8ce6b7c
c37dd9b
d09bf37
9a941d7
c4228c0
9488822
c4d7fd6
a8831aa
2fdef53
d0330d7
c85396d
9d6c6f8
41e016f
6cd7a27
ba8ba75
39ba6f0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
const path = require('path'); | ||
|
||
class ResourceInterface { | ||
constructor(compilation, options = {}) { | ||
this.compilation = compilation; | ||
this.options = options; | ||
this.extensions = []; | ||
this.contentType = ''; | ||
} | ||
|
||
// hidden API? | ||
shouldResolve(url) { | ||
const { extensions } = this; | ||
|
||
return extensions.length && extensions.length > 0 | ||
|| extensions[0] === '*' | ||
|| extensions.indexOf(path.extname(url) >= 0); | ||
} | ||
|
||
async resolve(url) { | ||
return Promise.resolve(url); | ||
} | ||
|
||
// introduce a new resource type to the browser, on the fly, ex: `<script src="index.ts">` | ||
// eslint-disable-next-line no-unused-vars | ||
shouldServe(url, headers) { | ||
return this.extensions.indexOf(path.extname(url)) >= 0; | ||
} | ||
|
||
// eslint-disable-next-line no-unused-vars | ||
async serve(url, headers) { | ||
return Promise.resolve({}); | ||
} | ||
|
||
// handle an already resolved / served resource | ||
// eslint-disable-next-line no-unused-vars | ||
shouldIntercept(url, headers) { | ||
return false; | ||
} | ||
|
||
// eslint-disable-next-line no-unused-vars | ||
async intercept(contents, headers) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting idea +1 |
||
return Promise.resolve(contents); | ||
} | ||
|
||
// handle a (final) resource type post build, pre optimize, | ||
// ex: remove es shim <script>, convert .ts -> .js and update path references | ||
// this is only an _index.html_ file, BYOA (Bring Your Own AST) | ||
// eslint-disable-next-line no-unused-vars | ||
shouldOptimize(contents, url) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perfect for post-serialize plugin functionality |
||
return false; | ||
} | ||
|
||
// eslint-disable-next-line no-unused-vars | ||
async optimize (contents, url) { | ||
return Promise.resolve(contents); | ||
} | ||
} | ||
|
||
module.exports = { | ||
ResourceInterface | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,53 @@ | ||
const BrowserRunner = require('../lib/browser'); | ||
const { promises: fsp } = require('fs'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const pluginResourceStandardHtml = require('../plugins/resource/plugin-standard-html'); | ||
|
||
module.exports = serializeCompilation = async (compilation) => { | ||
const compilationCopy = Object.assign({}, compilation); | ||
const browserRunner = new BrowserRunner(); | ||
const optimizeResources = [ | ||
pluginResourceStandardHtml.provider(compilationCopy), | ||
...compilation.config.plugins.filter((plugin) => { | ||
const provider = plugin.provider(compilationCopy); | ||
|
||
return plugin.type === 'resource' | ||
&& provider.shouldOptimize | ||
&& provider.optimize; | ||
}).map((plugin) => { | ||
return plugin.provider(compilationCopy); | ||
}) | ||
]; | ||
|
||
await browserRunner.init(); | ||
|
||
const runBrowser = async (serverUrl, pages, outputDir) => { | ||
|
||
try { | ||
return Promise.all(pages.map(async(page) => { | ||
const { route } = page; | ||
console.info('serializing page...', route); | ||
|
||
return await browserRunner | ||
.serialize(`${serverUrl}${route}`) | ||
.then(async (html) => { | ||
.then(async (indexHtml) => { | ||
const outputPath = `${outputDir}${route}index.html`; | ||
|
||
// TODO allow setup / teardown (e.g. module shims, then remove module-shims) | ||
let htmlModified = html; | ||
|
||
// TODO should really be happening via plugins or other standardize setup / teardown mechanism | ||
htmlModified = htmlModified.replace(/<script src="\/node_modules\/@webcomponents\/webcomponentsjs\/webcomponents-bundle.js"><\/script>/, ''); | ||
htmlModified = htmlModified.replace(/<script type="importmap-shim">.*?<\/script>/s, ''); | ||
htmlModified = htmlModified.replace(/<script defer="" src="\/node_modules\/es-module-shims\/dist\/es-module-shims.js"><\/script>/, ''); | ||
htmlModified = htmlModified.replace(/<script type="module-shim"/g, '<script type="module"'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💯 agree with this refactor. |
||
|
||
// console.debug('final HTML', htmlModified); | ||
console.info(`Serializing complete for page ${route}.`); | ||
// console.debug(`outputting to... ${outputDir.replace(`${process.cwd()}`, '.')}${outputPath}`); | ||
|
||
const htmlOptimized = await optimizeResources.reduce(async (htmlPromise, resource) => { | ||
const html = await htmlPromise; | ||
|
||
return resource.shouldOptimize(html) | ||
? resource.optimize(html) | ||
: Promise.resolve(html); | ||
}, Promise.resolve(indexHtml)); | ||
|
||
if (!fs.existsSync(path.join(outputDir, route))) { | ||
fs.mkdirSync(path.join(outputDir, route), { | ||
recursive: true | ||
}); | ||
} | ||
|
||
await fsp.writeFile(outputPath, htmlModified); | ||
await fs.promises.writeFile(outputPath, htmlOptimized); | ||
}); | ||
})); | ||
} catch (e) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Was curious how we were going to implement this in rollup. This is exactly whats needed.