Last active
February 10, 2020 05:07
-
-
Save xiaogdgenuine/921c643bc4eedd029cdf2bfe11c79a00 to your computer and use it in GitHub Desktop.
A babel plugin for take prefetch control from webpack (Just a prove of concept)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const lazyPageA = createLoadable( | |
prefetchable(() => import('./pageA.js'), 'pageA-chunk', '.js') | |
) | |
// This just prefetch, doesn't evaluate the JS | |
a.onmousehover = () => lazyPageA.prefetch() | |
// This do parse, evaluate the JS | |
a.onclick = () => lazyPageA.load().then(...) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { prefetchable } from "webpack-prefetcher"; | |
const lazyPageA = createLoadable( | |
prefetchable(() => import('./pageA.js')) | |
) | |
// This just prefetch, doesn't evaluate the JS | |
a.onmousehover = () => lazyPageA.prefetch() | |
// This do parse, evaluate the JS | |
a.onclick = () => lazyPageA.load().then(...) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// The inspiration is come from | |
// https://github.com/sebastian-software/babel-plugin-smart-webpack-import | |
const {basename, extname} = require("path"); | |
const t = require('babel-types'); | |
function collectImportCallPaths(startPath) { | |
const imports = []; | |
startPath.traverse({ | |
Import: function Import(importPath) { | |
imports.push(importPath) | |
} | |
}); | |
return imports | |
} | |
function getImportArgPath(path) { | |
return path.parentPath.get("arguments")[0] | |
} | |
const visited = Symbol("visited"); | |
function processImport(path, state, callPath) { | |
if (path[visited]) { | |
return | |
} | |
path[visited] = true; | |
const importArg = getImportArgPath(path); | |
const importArgNode = importArg.node; | |
const {leadingComments = []} = importArgNode; | |
const request = importArgNode.value; | |
function getChunkName(chunkNameComment) { | |
return chunkNameComment.value.replace('webpackChunkName:', '') | |
.replace(/'/g, '').trim() | |
} | |
// There exists the possibility of non usable value. Typically only | |
// when the user has import() statements with other complex data, but | |
// not a plain string or template string. We handle this gracefully by ignoring. | |
if (request == null) { | |
return | |
} | |
const chunkExtension = extname(request); | |
let chunkNameComment = leadingComments.find(x => x.value.trim().startsWith("webpackChunkName:")); | |
let chunkName = `${basename(request, extname(request))}-chunk`; | |
// This is not a prefetch import and also don't have chunk name | |
if (!chunkNameComment) { | |
// Set a chunk name for it | |
importArg.addComment('leading', `webpackChunkName: '${chunkName}'`) | |
} else { | |
// Get the chunk name | |
chunkName = getChunkName(chunkNameComment); | |
} | |
// Add the chunkName to the prefetchable function call | |
callPath.node.arguments.push(t.stringLiteral(chunkName)); | |
if (chunkExtension) { | |
callPath.node.arguments.push(t.stringLiteral(chunkExtension)); | |
} | |
} | |
module.exports = function webpackImportPrefetch() { | |
return { | |
name: "webpack-import-prefetch", | |
visitor: { | |
CallExpression(path, state) { | |
if (path.node.callee.name === 'prefetchable') { | |
const imports = collectImportCallPaths(path); | |
imports.forEach((importCall) => processImport(importCall, state, path)) | |
} | |
} | |
} | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export class Prefetcher { | |
static manifest = { | |
"pageA.js": "/pageA.hash.js", | |
"pageA.css": "/pageA.hash.css", | |
"app.js": "/app.hash.js", | |
"index.html": "/index.html" | |
} | |
static function prefetch(chunkId, chunkExtension, as) { | |
const link = document.createElement('link') | |
link.rel = "prefetch" | |
link.as = as | |
link.href = Prefetcher.manifest[chunkId + chunkExtension] | |
document.head.appendChild(link) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment