This commit is contained in:
Clement Bois 2019-06-19 12:15:48 +02:00
parent f76e15c320
commit 4391338adf
21 changed files with 2037 additions and 2298 deletions

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# Vue Pages Router
Unsafe component to load dynamic components using vue-sfc-compiler.

1
compiler/dist/core/pages-router.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,16 +0,0 @@
Vue.component('raith-test1', {
template: `<div><p>{{ yolol }}</p></div>`,
methods: {},
data() {
return {
yolol: null
}
},
created() {
API.pages().then(resp => {
this.yolol = Object.values(resp.data)[0]
}).catch(err => {
this.yolol = err.response.statusText
})
}
})

File diff suppressed because one or more lines are too long

View File

@ -1,16 +0,0 @@
Vue.component('raith-test2', {
template: `<div><p>{{ yolol }}</p></div>`,
methods: {},
data() {
return {
yolol: null
}
},
created() {
API.pages().then(resp => {
this.yolol = resp.data
}).catch(err => {
this.yolol = err.response.statusText
})
}
})

View File

@ -2,5 +2,5 @@
// BROWSER COMPONENT ENTRY FILE // BROWSER COMPONENT ENTRY FILE
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
import Component from './src/__FILE__'; import Component from './src/__FILE__'
Vue.component(Component.name, Component); Vue.component((Component.options || Component).name, Component)

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,16 @@
{ {
"name": "vue-browser-component", "name": "vue-browser-component",
"version": "1.0.0", "version": "1.1.0",
"description": "A VueJS CLI template for compiling standalone components from .vue files", "description": "A VueJS CLI template for compiling standalone components from .vue files",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"build": "webpack --env.file", "build": "webpack --env.file",
"serve": "webpack -d --watch --env.file", "build:dev": "webpack -d --env.file",
"test": "echo \"Error: no test specified\" && exit 1" "watch": "webpack -d --watch --env.file"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/RonnieSan/browser-components.git" "url": "git+https://git.wadza.fr/me/vue-sfc-compiler.git"
}, },
"keywords": [ "keywords": [
"vue", "vue",
@ -18,39 +18,47 @@
"browser", "browser",
"component" "component"
], ],
"author": "RonnieSan", "author": "Shu",
"contributors": [
"RonnieSan"
],
"license": "MIT", "license": "MIT",
"bugs": { "bugs": {
"url": "https://github.com/RonnieSan/browser-components/issues" "url": "https://github.com/sheychen290/vue-sfc-compiler/issues"
}, },
"homepage": "https://github.com/RonnieSan/browser-components#readme", "homepage": "https://git.wadza.fr/me/vue-sfc-compiler",
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.2.0", "@babel/cli": "^7.4.4",
"@babel/core": "^7.2.2", "@babel/core": "^7.4.5",
"@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/preset-env": "^7.2.0", "@babel/preset-env": "^7.4.5",
"autoprefixer": "^8.3.0", "autoprefixer": "^8.6.5",
"babel-loader": "^8.0.5", "babel-loader": "^8.0.6",
"core-js": "^2.6.9",
"css-loader": "^0.28.11", "css-loader": "^0.28.11",
"file-loader": "^1.1.11", "file-loader": "^1.1.11",
"friendly-errors-webpack-plugin": "^1.7.0", "friendly-errors-webpack-plugin": "^1.7.0",
"less": "^3.0.2", "less": "^3.9.0",
"less-loader": "^4.1.0", "less-loader": "^4.1.0",
"node-sass": "^4.11.0", "node-sass": "^4.12.0",
"optimize-css-assets-webpack-plugin": "^4.0.0", "optimize-css-assets-webpack-plugin": "^4.0.3",
"sass-loader": "^7.0.1",
"string-replace-webpack-plugin": "^0.1.3",
"url-loader": "^1.0.1",
"vue-loader": "^15.4.2",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.5.22",
"webpack": "^4.6.0",
"webpack-cli": "^3.2.1",
"pug": "^2.0.3", "pug": "^2.0.3",
"pug-plain-loader": "^1.0.0" "pug-plain-loader": "^1.0.0",
"sass-loader": "^7.1.0",
"string-replace-webpack-plugin": "^0.1.3",
"ts-loader": "^6.0.3",
"typescript": "^3.5.2",
"url-loader": "^1.1.2",
"vue-loader": "^15.7.0",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.6.10",
"webpack": "^4.34.0",
"webpack-cli": "^3.3.4"
}, },
"dependencies": { "dependencies": {
"vue": "^2.5.22" "vue": "^2.6.10",
"vue-class-component": "^7.1.0",
"vue-property-decorator": "^8.2.1"
}, },
"babel": { "babel": {
"presets": [ "presets": [
@ -61,9 +69,5 @@
} }
] ]
] ]
}, }
"browserslist": [
"last 2 versions",
"ie >= 11"
]
} }

View File

@ -4,7 +4,5 @@ p(style="color: red") Can't load module
</template> </template>
<script> <script>
export default { export default { }
name: 'rp-page-error'
}
</script> </script>

View File

@ -4,7 +4,5 @@ p Loading...
</template> </template>
<script> <script>
export default { export default { }
name: 'rp-page-loader'
}
</script> </script>

View File

@ -1,33 +1,24 @@
<template lang="pug"> <template lang="pug">
div .pages
#pages-list .pages-list
p(v-if="pages.error" style="color: orangered") {{ pages.error }} slot(v-if="pages.error" name="error") {{ pages.error }}
div(v-else-if="pages.data") slot(v-else-if="pages.data" name="list")
template(v-for="(page, id) in pages.data") template(v-for="(page, id) in pages.data")
button(v-if="activePage != id" @click="showPage(id)") {{ page.name }} button(v-if="activePage != id" @click="showPage(id)") {{ page.name }}
p(v-else) {{ page.name }} p(v-else) {{ page.name }}
main-loader(v-else) slot(v-else name="loader") Loading...
#active-page .active-page
div(v-if="activePage") div(v-if="activePage")
keep-alive keep-alive
div(:is="activeComponent") div(:is="activeComponent")
p Hello world
</template> </template>
<script> <script>
import MainLoader from './rp-main-loader.vue' import PageLoader from './components/loader.vue'
import PageLoader from './rp-page-loader.vue' import PageError from './components/error.vue'
import PageError from './rp-page-error.vue'
import API from 'API'
const PAGE_PREFIX = 'raith-'
export default { export default {
name : 'rp-pages', name: 'pages-router',
components: {
'main-loader': MainLoader
},
data() { data() {
return { return {
pages: { pages: {
@ -36,10 +27,43 @@ export default {
}, },
activePage: null activePage: null
} }
}, },
props: {
loader: {
type: Object,
default() {
return PageLoader
}
},
error: {
type: Object,
default() {
return PageError
}
},
prefix: {
type: String,
default: 'page-'
},
retry: {
type: Boolean,
default: false
},
source: {
required: true
},
timeout: {
type: Number,
default: 5000
},
title: {
type: String,
default: 'Router'
}
},
created() { created() {
API.pages().then(resp => { // Load pages this.source.then(data => { // Load pages
this.pages.data = resp.data this.pages.data = data
const loading = () => { // Show page from url or default one const loading = () => { // Show page from url or default one
this.showPage(window.location.hash.length > 0 ? this.showPage(window.location.hash.length > 0 ?
window.location.hash.substr(2) : window.location.hash.substr(2) :
@ -47,21 +71,21 @@ export default {
} }
this.$nextTick(loading) this.$nextTick(loading)
window.onhashchange = loading window.onhashchange = loading
}).catch(err => { }).catch(error => {
this.pages.error = err.response.statusText this.pages.error = error
}) })
}, },
computed: { computed: {
activeComponent() { activeComponent() {
return PAGE_PREFIX + this.activePage return this.prefix + this.activePage
} }
}, },
methods: { methods: {
showPage(id) { showPage(id) {
const key = PAGE_PREFIX + id const key = this.prefix + id
if (!(id in this.pages.data)) { if (!(id in this.pages.data)) {
console.error(`Module not found: ${id}`) console.error(`Module not found: ${id}`)
this.$options.components[key] = PageError this.$options.components[key] = this.error
return; return;
} }
const mod = this.pages.data[id] const mod = this.pages.data[id]
@ -75,11 +99,18 @@ export default {
const load = () => loaded() ? const load = () => loaded() ?
resolve(Vue.options.components[key]) : reject() resolve(Vue.options.components[key]) : reject()
if (loaded() || document.querySelector('script[src="' + mod.src + '"]')) { //allready loaded if (loaded() || (!this.retry && document.querySelector(`script[src="${mod.src}"]`))) { // Allready loaded
load() load()
return; return;
} }
const remover = fn => e => {
if(this.retry) {
document.head.removeChild(e.target)
}
fn()
}
const el = document.createElement('script') const el = document.createElement('script')
el.type = 'text/javascript' el.type = 'text/javascript'
@ -88,20 +119,18 @@ export default {
if (mod.integrity != null) if (mod.integrity != null)
el.integrity = mod.integrity el.integrity = mod.integrity
el.addEventListener('load', load) el.addEventListener('load', remover(load))
el.addEventListener('error', reject) el.addEventListener('error', remover(reject))
el.addEventListener('abort', reject) el.addEventListener('abort', remover(reject))
//setTimeout(() => { document.head.appendChild(el)
document.head.appendChild(el)
//}, 2000)
}), }),
loading: PageLoader, loading: this.loader,
error: PageError, error: this.error,
timeout: 5000 timeout: this.timeout
}) })
} }
document.title = `Raith - ${mod.name}` document.title = `${this.title} - ${mod.name}`
window.history.pushState({}, document.title, "/#/" + id) window.history.pushState({}, document.title, "/#/" + id)
this.activePage = id this.activePage = id
} }

View File

@ -1,10 +0,0 @@
<template lang="pug">
p Loading...
//TODO: Cool loader
</template>
<script>
export default {
name: 'rp-main-loader'
}
</script>

View File

@ -4,18 +4,14 @@ p {{ yolol }}
<script> <script>
export default { export default {
name: 'raith-test1', //Really important name: 'page-test1', //Really important
data() { data() {
return { return {
yolol: null yolol: null
} }
}, },
created() { created() {
API.pages().then(resp => { this.yolol = 'hello'
this.yolol = Object.values(resp.data)[0]
}).catch(err => {
this.yolol = err.response.statusText
})
} }
} }
</script> </script>

View File

@ -2,20 +2,16 @@
p {{ yolo }} p {{ yolo }}
</template> </template>
<script> <script lang="ts">
export default { import Vue from 'vue'
name: 'raith-test2', //Really important import Component from 'vue-class-component'
data() {
return { @Component({ name: 'page-test2' }) //Really important
yolo: null export default class Test2 extends Vue {
} yolo = 'loading'
},
created() { created() {
API.pages().then(resp => { this.yolo = 'holla'
this.yolo = resp.data
}).catch(err => {
this.yolo = err.response.statusText
})
} }
} }
</script> </script>

9
compiler/tsconfig.json Normal file
View File

@ -0,0 +1,9 @@
{
"compilerOptions": {
"target": "es5",
"strict": true,
"module": "es2015",
"moduleResolution": "node",
"experimentalDecorators": true,
}
}

4
compiler/vue-shims.d.ts vendored Normal file
View File

@ -0,0 +1,4 @@
declare module "*.vue" {
import Vue from "vue";
export default Vue;
}

View File

@ -6,10 +6,10 @@
// webpack --env.file="./path/to/file" --relative to the src folder // webpack --env.file="./path/to/file" --relative to the src folder
// Import dependencies // Import dependencies
const path = require('path'); const path = require('path');
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin'); const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');
const StringReplacePlugin = require('string-replace-webpack-plugin'); const StringReplacePlugin = require('string-replace-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin'); const VueLoaderPlugin = require('vue-loader/lib/plugin');
function resolve(dir) { function resolve(dir) {
return path.resolve(__dirname, dir); return path.resolve(__dirname, dir);
@ -21,31 +21,29 @@ module.exports = (env) => {
const filepath = path.dirname(env.file); const filepath = path.dirname(env.file);
return { return {
mode : 'production', mode: 'production',
entry : { entry: {
[filename] : './entry.js' [filename]: './entry.js'
}, },
output : { output: {
filename : '[name].js', filename: '[name].js',
path: path.resolve(__dirname, 'dist', filepath) path: path.resolve(__dirname, 'dist', filepath)
}, },
resolve : { resolve: {
extensions : ['.vue', '.js'], extensions: ['.ts', '.vue', '.js'],
alias : { alias: {
'vue$' : resolve('node_modules/vue/dist/vue.min.js'), 'vue$': resolve('node_modules/vue/dist/vue.min.js'),
'@' : resolve('src') '@': resolve('src')
} }
}, },
externals : { externals: {
vue : 'Vue', vue: 'Vue'
lodash: 'lodash',
API: 'API'
}, },
module : { module: {
rules : [ rules: [
{ {
test : /entry\.js$/, test: /entry\.js$/,
loader : StringReplacePlugin.replace({ loader: StringReplacePlugin.replace({
replacements: [ replacements: [
{ {
pattern: /__FILE__/ig, pattern: /__FILE__/ig,
@ -53,16 +51,25 @@ module.exports = (env) => {
return env.file; return env.file;
} }
} }
]}) ]
})
}, },
{ {
test : /\.vue$/, test: /\.vue$/,
loader : 'vue-loader' loader: 'vue-loader'
}, },
{ {
test : /\.js$/, test: /\.tsx?$/,
loader : 'babel-loader', loader: 'ts-loader',
include : [ exclude: /node_modules/,
options: {
appendTsSuffixTo: [/\.vue$/],
}
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [
resolve('src') resolve('src')
], ],
exclude: file => ( exclude: file => (
@ -71,37 +78,37 @@ module.exports = (env) => {
) )
}, },
{ {
test : /\.css$/, test: /\.css$/,
use : [ use: [
'vue-style-loader', 'vue-style-loader',
'css-loader' 'css-loader'
] ]
}, },
{ {
test : /\.less$/, test: /\.less$/,
use : [ use: [
'vue-style-loader', 'vue-style-loader',
'css-loader', 'css-loader',
'less-loader' 'less-loader'
] ]
}, },
{ {
test : /\.scss$/, test: /\.scss$/,
use : [ use: [
'vue-style-loader', 'vue-style-loader',
'css-loader', 'css-loader',
'sass-loader' 'sass-loader'
] ]
}, },
{ {
test : /\.sass$/, test: /\.sass$/,
use : [ use: [
'vue-style-loader', 'vue-style-loader',
'css-loader', 'css-loader',
{ {
loader : 'sass-loader', loader: 'sass-loader',
options : { options: {
indentedSyntax : true indentedSyntax: true
} }
} }
] ]
@ -112,7 +119,14 @@ module.exports = (env) => {
} }
] ]
}, },
plugins : [ devServer: {
historyApiFallback: true,
noInfo: true
},
performance: {
hints: false
},
plugins: [
new VueLoaderPlugin(), new VueLoaderPlugin(),
new OptimizeCSSPlugin({ new OptimizeCSSPlugin({
cssProcessorOptions: { cssProcessorOptions: {

View File

@ -4,20 +4,24 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Raith</title> <title>Vue Pages Router</title>
<script src="lib/axios.js"></script> <script src="lib/axios.js"></script>
<script src="lib/API.js"></script>
<script src="lib/vue.full.js"></script> <script src="lib/vue.full.js"></script>
<script src="compiler/dist/core/rp-pages.js"></script> <script src="compiler/dist/core/pages-router.js"></script>
</head> </head>
<body> <body>
<div id="app"> <div id="app">
<noscript>Raith client need javascript enabled to work correctly. Sorry</noscript> <noscript>Needs javascript enabled to work correctly. Sorry</noscript>
<rp-pages></rp-pages> <pages-router :source="pages"></pages-router>
</div> </div>
<script> <script>
var app = new Vue({ var app = new Vue({
el: '#app' el: '#app',
data: {
pages: axios.get('pages.json')
.then(res => res.data)
.catch(err => err.response.statusText)
}
}) })
</script> </script>
</body> </body>

View File

@ -1,14 +0,0 @@
const _api = axios.create({
baseURL: './',
timeout: 1000/*,
headers: {
'X-Custom-Header': 'foobar'
}*/
})
const API = {
http: _api,
pages() {
return _api.get('pages.json')
}
}