|
11 | 11 | * [Dynamic component (`:is` Special Attribute)](#dynamic-component-is-special-attribute)
|
12 | 12 | * [Nested components](#nested-components)
|
13 | 13 | * [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) |
14 | 15 | <!--/toc-->
|
15 | 16 |
|
16 | 17 | # Examples
|
@@ -738,6 +739,118 @@ In the following example we use a trick to preserve reactivity through the `Vue.
|
738 | 739 | [:top:](#readme)
|
739 | 740 |
|
740 | 741 |
|
| 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 | + |
741 | 854 |
|
742 | 855 | <!---
|
743 | 856 |
|
|
0 commit comments