microsite
Version:
<br /> <br />
100 lines (84 loc) • 3.29 kB
JavaScript
const { resolve } = require('path');
const EXTS = ['.js', '.jsx', '.ts', '.tsx', '.mjs'];
const IMPORT_REGEX = /import(?:['"\s]*([\w*${}\s,]+)from\s*)?['"\s]['"\s](.*[@\w_-]+)['"\s].*/gm;
const scanImports = (contents) => {
let result;
let imports = [];
while (result = IMPORT_REGEX.exec(contents)) {
const [_, statement = null, specifier] = result;
imports.push({ statement, specifier });
}
return imports;
}
/** Automatically inject `h` and `Fragment` */
const injectJSX = (contents) => {
let toInject = [];
let imports = scanImports(contents);
const preactImports = imports.filter(i => i.specifier.indexOf('preact') > -1);
const imported = {
h: preactImports.length > 0 ? preactImports.some(({ statement }) => /\bh\b/.test(statement)) : false,
Fragment: preactImports.length > 0 ? preactImports.some(({ statement }) => /\bFragment\b/.test(statement)) : false
}
if (/\bh\(/g.test(contents) && !imported.h) toInject.push('h');
if (/\bFragment\b/g.test(contents) && !imported.Fragment) toInject.push('Fragment');
if (toInject.length > 0) {
contents = `import { ${toInject.join(', ')} } from 'preact';\n` + contents;
}
return contents;
}
module.exports = function plugin() {
return {
name: '@microsite/snowpack',
knownEntrypoints: ['preact', 'microsite/client/hooks', 'microsite/client/csr', 'microsite/error', 'microsite/document', 'microsite/head'],
async transform({ id, contents, isDev, fileExt }) {
if (!EXTS.includes(fileExt)) return;
contents = injectJSX(contents);
if (!isDev) {
// shim fetch for files that use it
if (/\bfetch\(/g.test(contents)) return `import fetch from 'microsite/server/fetch';\n${contents}`;
return contents;
}
if (id.endsWith('global/index.js')) {
return `${contents}\nif (import.meta.hot) import.meta.hot.decline();`
}
if (id.indexOf('src/pages') > -1) {
return `${contents}
const hash = s => s.split('').reduce((a,b) => (((a << 5) - a) + b.charCodeAt(0))|0, 0)
export let $hashes = {};
if (import.meta.hot) {
let $prev = $hashes;
import(\`$\{import.meta.hot.id}\`).then(module => {
$hashes = {
getStaticProps: module.default.getStaticProps ? hash(\`$\{module.default.getStaticProps}\`) : undefined,
getStaticPaths: module.default.getStaticPaths ? hash(\`$\{module.default.getStaticPaths}\`) : undefined
}
import.meta.hot.dispose(() => {
import.meta.hot.data = { $hashes };
})
});
import.meta.hot.accept(({ module }) => {
$prev = import.meta.hot.data.$hashes || module.$hashes;
$hashes = {
getStaticProps: module.default.getStaticProps ? hash(\`$\{module.default.getStaticProps}\`) : undefined,
getStaticPaths: module.default.getStaticPaths ? hash(\`$\{module.default.getStaticPaths}\`) : undefined
}
if ($prev && $hashes) {
if ($prev.getStaticProps !== $hashes.getStaticProps) {
import.meta.hot.invalidate();
}
if ($prev.getStaticPaths !== $hashes.getStaticPaths) {
import.meta.hot.invalidate();
}
}
});
}
`;
}
return contents;
},
config(snowpackConfig) {
snowpackConfig.devOptions.fallback = null;
return snowpackConfig;
},
};
};