Skip to content

Commit 607a21e

Browse files
wip(docs): add getResource() example
1 parent 7509709 commit 607a21e

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

docs/examples.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
* [Dynamic component (`:is` Special Attribute)](#dynamic-component-is-special-attribute)
1212
* [Nested components](#nested-components)
1313
* [Example using SFC Custom Blocks for i18n](#example-using-sfc-custom-blocks-for-i18n)
14+
* [Example using getResource() and process the files like webpack does](#example-using-getresource-and-process-the-files-like-webpack-does)
1415
<!--/toc-->
1516

1617
# Examples
@@ -738,6 +739,118 @@ In the following example we use a trick to preserve reactivity through the `Vue.
738739
[:top:](#readme)
739740

740741

742+
## Example using getResource() and process the files like webpack does
743+
744+
<!--example:source:getResource_loaders-->
745+
```html
746+
<!DOCTYPE html>
747+
<html>
748+
<body>
749+
<script src="https://unpkg.com/vue@next/dist/vue.runtime.global.prod.js"></script>
750+
<script src="vue3-sfc-loader.js"></script>
751+
<script>
752+
753+
/* <!-- */
754+
const config = {
755+
files: {
756+
'/main.vue': `
757+
<template>
758+
<pre><b>'url!./circle.svg' -> </b>{{ require('url!./circle.svg') }}</pre>
759+
<img width="50" height="50" src="~url!./circle.svg" />
760+
<pre><b>'file!./circle.svg' -> </b>{{ require('file!./circle.svg') }}</pre>
761+
<img width="50" height="50" src="~file!./circle.svg" />
762+
</template>
763+
`,
764+
'/circle.svg': `
765+
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
766+
<circle cx="50" cy="50" r="50" />
767+
</svg>
768+
`,
769+
}
770+
};
771+
/* --> */
772+
773+
const options = {
774+
moduleCache: {
775+
vue: Vue,
776+
'file!'(content, path, extname, options) {
777+
778+
return String(new URL(path, window.location));
779+
},
780+
'url!'(content, path, extname, options) {
781+
782+
if ( extname === '.svg' )
783+
return `data:image/svg+xml;base64,${ btoa(content) }`;
784+
785+
throw new Error(`${ extname } not handled by url!`);
786+
},
787+
},
788+
handleModule(extname, source, path, options) {
789+
790+
switch (extname) {
791+
case '.svg': return source;
792+
}
793+
},
794+
getFile(url, options) {
795+
796+
return config.files[url] || (() => { throw new Error('404 ' + url) })();
797+
},
798+
getResource({ refPath, relPath }, options) {
799+
800+
const { moduleCache, pathHandlers: { resolve }, getFile } = options;
801+
802+
const [ resourceRelPath, ...loaders ] = relPath.match(/([^!]+!)|[^!]+$/g).reverse();
803+
804+
// process a content through the loaders
805+
const processContentThroughLoaders = (content, path, extname, options) => {
806+
807+
return loaders.reduce((content, loader) => {
808+
809+
return moduleCache[loader](content, path, extname);
810+
}, content);
811+
}
812+
813+
// get the actual path of the file
814+
const path = resolve({ refPath, relPath: resourceRelPath });
815+
816+
// the resource id must be unique in its path context
817+
const id = loaders.join('') + path;
818+
819+
return {
820+
id,
821+
path,
822+
async getContent() {
823+
824+
const { content, extname } = await getFile(path);
825+
826+
return {
827+
content: processContentThroughLoaders(content, path, extname),
828+
extname,
829+
};
830+
}
831+
};
832+
},
833+
addStyle(textContent) {
834+
835+
const style = Object.assign(document.createElement('style'), { textContent });
836+
const ref = document.head.getElementsByTagName('style')[0] || null;
837+
document.head.insertBefore(style, ref);
838+
},
839+
}
840+
841+
const app = Vue.createApp(Vue.defineAsyncComponent(() => window['vue3-sfc-loader'].loadModule('/main.vue', options)));
842+
app.mount(document.body);
843+
console.log(options.moduleCache)
844+
845+
</script>
846+
</body>
847+
</html>
848+
```
849+
<!--example:target:getResource_loaders-->
850+
[open in JSBin ▶](http://jsbin.com/?html,output&html=%3C!DOCTYPE+html%3E%0A%3Chtml%3E%0A%3Cbody%3E%0A%3Cscript+src%3D%22https%3A%2F%2Funpkg.com%2Fvue%40next%2Fdist%2Fvue.runtime.global.prod.js%22%3E%3C%2Fscript%3E%0A%3Cscript+src%3D%22vue3-sfc-loader.js%22%3E%3C%2Fscript%3E%0A%3Cscript%3E%0A%0A%09%2F*+%3C!--+*%2F%0A%09const+config+%3D+%7B%0A%09%09files%3A+%7B%0A%09%09%09'%2Fmain.vue'%3A+%60%0A%09%09%09%09%3Ctemplate%3E%0A%09%09%09%09%09%3Cpre%3E%3Cb%3E'url!.%2Fcircle.svg'+-%3E+%3C%2Fb%3E%7B%7B+require('url!.%2Fcircle.svg')+%7D%7D%3C%2Fpre%3E%0A%09%09%09%09%09%3Cimg+width%3D%2250%22+height%3D%2250%22+src%3D%22~url!.%2Fcircle.svg%22+%2F%3E%0A%09%09%09%09%09%3Cpre%3E%3Cb%3E'file!.%2Fcircle.svg'+-%3E+%3C%2Fb%3E%7B%7B+require('file!.%2Fcircle.svg')+%7D%7D%3C%2Fpre%3E%0A%09%09%09%09%09%3Cimg+width%3D%2250%22+height%3D%2250%22+src%3D%22~file!.%2Fcircle.svg%22+%2F%3E%0A%09%09%09%09%3C%2Ftemplate%3E%0A%09%09%09%60%2C%0A%09%09%09'%2Fcircle.svg'%3A+%60%0A%09%09%09%09%3Csvg+viewBox%3D%220+0+100+100%22+xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%09%09%09%09%09%3Ccircle+cx%3D%2250%22+cy%3D%2250%22+r%3D%2250%22+%2F%3E%0A%09%09%09%09%3C%2Fsvg%3E%0A%09%09%09%60%2C%0A%09%09%7D%0A%09%7D%3B%0A%09%2F*+--%3E+*%2F%0A%0A%09const+options+%3D+%7B%0A%09%09moduleCache%3A+%7B%0A%09%09%09vue%3A+Vue%2C%0A%09%09%09'file!'(content%2C+path%2C+extname%2C+options)+%7B%0A%0A%09%09%09%09return+String(new+URL(path%2C+window.location))%3B%0A%09%09%09%7D%2C%0A%09%09%09'url!'(content%2C+path%2C+extname%2C+options)+%7B%0A%0A%09%09%09%09if+(+extname+%3D%3D%3D+'.svg'+)%0A%09%09%09%09%09return+%60data%3Aimage%2Fsvg%2Bxml%3Bbase64%2C%24%7B+btoa(content)+%7D%60%3B%0A%0A%09%09%09%09throw+new+Error(%60%24%7B+extname+%7D+not+handled+by+url!%60)%3B%0A%09%09%09%7D%2C%0A%09%09%7D%2C%0A%09%09handleModule(extname%2C+source%2C+path%2C+options)+%7B%0A%0A%09%09%09switch+(extname)+%7B%0A%09%09%09%09case+'.svg'%3A+return+source%3B%0A%09%09%09%7D%0A%09%09%7D%2C%0A%09%09getFile(url%2C+options)+%7B%0A%0A%09%09%09return+config.files%5Burl%5D+%7C%7C+(()+%3D%3E+%7B+throw+new+Error('404+'+%2B+url)+%7D)()%3B%0A%09%09%7D%2C%0A%09%09getResource(%7B+refPath%2C+relPath+%7D%2C+options)+%7B%0A%0A%09%09%09const+%7B+moduleCache%2C+pathHandlers%3A+%7B+resolve+%7D%2C+getFile+%7D+%3D+options%3B%0A%0A%09%09%09const+%5B+resourceRelPath%2C+...loaders+%5D+%3D+relPath.match(%2F(%5B%5E!%5D%2B!)%7C%5B%5E!%5D%2B%24%2Fg).reverse()%3B%0A%0A%09%09%09%2F%2F+process+a+content+through+the+loaders%0A%09%09%09const+processContentThroughLoaders+%3D+(content%2C+path%2C+extname%2C+options)+%3D%3E+%7B%0A%09%09%09%09%0A%09%09%09%09return+loaders.reduce((content%2C+loader)+%3D%3E+%7B%0A%0A%09%09%09%09%09return+moduleCache%5Bloader%5D(content%2C+path%2C+extname)%3B%0A%09%09%09%09%7D%2C+content)%3B%0A%09%09%09%7D%0A%0A%09%09%09%2F%2F+get+the+actual+path+of+the+file%0A%09%09%09const+path+%3D+resolve(%7B+refPath%2C+relPath%3A+resourceRelPath+%7D)%3B%0A%0A%09%09%09%2F%2F+the+resource+id+must+be+unique+in+its+path+context%0A%09%09%09const+id+%3D+loaders.join('')+%2B+path%3B%0A%0A%09%09%09return+%7B%0A%09%09%09%09id%2C%0A%09%09%09%09path%2C%0A%09%09%09%09async+getContent()+%7B%0A%0A%09%09%09%09%09const+%7B+content%2C+extname+%7D+%3D+await+getFile(path)%3B%0A%0A%09%09%09%09%09return+%7B%0A%09%09%09%09%09%09content%3A+processContentThroughLoaders(content%2C+path%2C+extname)%2C%0A%09%09%09%09%09%09extname%2C%0A%09%09%09%09%09%7D%3B%0A%09%09%09%09%7D%0A%09%09%09%7D%3B%0A%09%09%7D%2C%0A%09%09addStyle(textContent)+%7B%0A%0A%09%09%09const+style+%3D+Object.assign(document.createElement('style')%2C+%7B+textContent+%7D)%3B%0A%09%09%09const+ref+%3D+document.head.getElementsByTagName('style')%5B0%5D+%7C%7C+null%3B%0A%09%09%09document.head.insertBefore(style%2C+ref)%3B%0A%09%09%7D%2C%0A%09%7D%0A%0A%09const+app+%3D+Vue.createApp(Vue.defineAsyncComponent(()+%3D%3E+window%5B'vue3-sfc-loader'%5D.loadModule('%2Fmain.vue'%2C+options)))%3B%0A%09app.mount(document.body)%3B%0A%09console.log(options.moduleCache)%0A%0A%3C%2Fscript%3E%0A%3C%2Fbody%3E%0A%3C%2Fhtml%3E%0A)<!--/example:target:getResource_loaders-->
851+
852+
[:top:](#readme)
853+
741854

742855
<!---
743856

0 commit comments

Comments
 (0)