Add Vue SFC compiler (using raw js component still possible as well as

Vue compiler vue.full.js)
This commit is contained in:
sheychen 2019-03-31 11:37:18 +02:00
parent 68e43c4b15
commit f76e15c320
24 changed files with 11208 additions and 12397 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
node_modules

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

File diff suppressed because one or more lines are too long

1
compiler/dist/test1.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -7,7 +7,7 @@ Vue.component('raith-test1', {
}
},
created() {
API.get('pages.json').then(resp => {
API.pages().then(resp => {
this.yolol = Object.values(resp.data)[0]
}).catch(err => {
this.yolol = err.response.statusText

1
compiler/dist/test2.js vendored Normal file
View File

@ -0,0 +1 @@
!function(t){var e={};function n(o){if(e[o])return e[o].exports;var r=e[o]={i:o,l:!1,exports:{}};return t[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=t,n.c=e,n.d=function(t,e,o){n.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:o})},n.r=function(t){Object.defineProperty(t,"__esModule",{value:!0})},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=0)}([function(t,e,n){"use strict";n.r(e);var o=function(){var t=this.$createElement;return(this._self._c||t)("p",[this._v(this._s(this.yolo))])};o._withStripped=!0;var r=function(t,e,n,o,r,i,s,a){var u,c="function"==typeof t?t.options:t;if(e&&(c.render=e,c.staticRenderFns=n,c._compiled=!0),o&&(c.functional=!0),i&&(c._scopeId="data-v-"+i),s?(u=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),r&&r.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(s)},c._ssrRegister=u):r&&(u=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),u)if(c.functional){c._injectStyles=u;var l=c.render;c.render=function(t,e){return u.call(e),l(t,e)}}else{var f=c.beforeCreate;c.beforeCreate=f?[].concat(f,u):[u]}return{exports:t,options:c}}({name:"raith-test2",data:function(){return{yolo:null}},created:function(){var t=this;API.pages().then(function(e){t.yolo=e.data}).catch(function(e){t.yolo=e.response.statusText})}},o,[],!1,null,null,null);r.options.__file="src/test2.vue";var i=r.exports;Vue.component(i.name,i)}]);

View File

@ -7,7 +7,7 @@ Vue.component('raith-test2', {
}
},
created() {
API.get('pages.json').then(resp => {
API.pages().then(resp => {
this.yolol = resp.data
}).catch(err => {
this.yolol = err.response.statusText

6
compiler/entry.js Normal file
View File

@ -0,0 +1,6 @@
// ----------------------------------------------------------------------
// BROWSER COMPONENT ENTRY FILE
// ----------------------------------------------------------------------
import Component from './src/__FILE__';
Vue.component(Component.name, Component);

19
compiler/index.html Normal file
View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>VueJS Component Test</title>
<script src="https://unpkg.com/vue"></script>
<script src="dist/example.js"></script>
</head>
<body>
<div id="wrapper">
<example></example>
</div>
<script>
var app = new Vue({
el : '#wrapper'
});
</script>
</body>
</html>

10767
compiler/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

69
compiler/package.json Normal file
View File

@ -0,0 +1,69 @@
{
"name": "vue-browser-component",
"version": "1.0.0",
"description": "A VueJS CLI template for compiling standalone components from .vue files",
"main": "index.js",
"scripts": {
"build": "webpack --env.file",
"serve": "webpack -d --watch --env.file",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/RonnieSan/browser-components.git"
},
"keywords": [
"vue",
"vuejs",
"browser",
"component"
],
"author": "RonnieSan",
"license": "MIT",
"bugs": {
"url": "https://github.com/RonnieSan/browser-components/issues"
},
"homepage": "https://github.com/RonnieSan/browser-components#readme",
"devDependencies": {
"@babel/cli": "^7.2.0",
"@babel/core": "^7.2.2",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/preset-env": "^7.2.0",
"autoprefixer": "^8.3.0",
"babel-loader": "^8.0.5",
"css-loader": "^0.28.11",
"file-loader": "^1.1.11",
"friendly-errors-webpack-plugin": "^1.7.0",
"less": "^3.0.2",
"less-loader": "^4.1.0",
"node-sass": "^4.11.0",
"optimize-css-assets-webpack-plugin": "^4.0.0",
"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-plain-loader": "^1.0.0"
},
"dependencies": {
"vue": "^2.5.22"
},
"babel": {
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage"
}
]
]
},
"browserslist": [
"last 2 versions",
"ie >= 11"
]
}

View File

@ -0,0 +1,5 @@
module.exports = {
plugins: [
require('autoprefixer')
]
};

View File

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

View File

@ -0,0 +1,10 @@
<template lang="pug">
p(style="color: red") Can't load module
//TODO: Sad error
</template>
<script>
export default {
name: 'rp-page-error'
}
</script>

View File

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

204
main.js → compiler/src/core/rp-pages.vue Executable file → Normal file
View File

@ -1,94 +1,110 @@
const API = axios.create({
baseURL: './',
timeout: 1000/*,
headers: {
'X-Custom-Header': 'foobar'
}*/
});
const PAGE_PREFIX = 'raith-'
const APP = new Vue({
el: '#app',
data: {
pages: {
error: null,
data: null
},
activePage: null
},
created() {
API.get('pages.json').then(resp => {
this.pages.data = resp.data
const loading = () => {
this.showPage(window.location.hash.length > 0 ?
window.location.hash.substr(2) :
Object.keys(this.pages.data)[0])
}
this.$nextTick(loading)
window.onhashchange = loading
}).catch(err => {
this.pages.error = err.response.statusText
})
},
computed: {
activeComponent() {
return PAGE_PREFIX + this.activePage
}
},
methods: {
showPage(id) {
const key = PAGE_PREFIX + id
if (!(id in this.pages.data)) {
const err = `Module not found: ${id}`
console.error(err)
this.$options.components[key] = {
template: `<p style="color: red">${err}</p>` //TODO: Sad error
}
return;
}
const mod = this.pages.data[id]
if (!(key in this.$options.components)) { // Must be load
this.$options.components[key] = () => ({
// Dynamicly load component
component: new Promise((resolve, reject) => {
const loaded = () => key in Vue.options.components
const load = () => loaded() ?
resolve(Vue.options.components[key]) : reject()
if (loaded() || document.querySelector('script[src="' + mod.src + '"]')) { //allready loaded
load()
return;
}
const el = document.createElement('script')
el.type = 'text/javascript'
el.async = true
el.src = mod.src
if (mod.integrity != null)
el.integrity = mod.integrity
el.addEventListener('load', load)
el.addEventListener('error', reject)
el.addEventListener('abort', reject)
document.head.appendChild(el)
}),
loading: {
template: '<p>Loading...</p>' //TODO: Cool loader
},
error: {
template: `<p style="color: red">Can't load module</p>` //TODO: Sad error
},
timeout: 5000
})
}
document.title = `Raith - ${mod.name}`
window.history.pushState({}, document.title, "/#/" + id);
this.activePage = id
}
}
})
<template lang="pug">
div
#pages-list
p(v-if="pages.error" style="color: orangered") {{ pages.error }}
div(v-else-if="pages.data")
template(v-for="(page, id) in pages.data")
button(v-if="activePage != id" @click="showPage(id)") {{ page.name }}
p(v-else) {{ page.name }}
main-loader(v-else)
#active-page
div(v-if="activePage")
keep-alive
div(:is="activeComponent")
p Hello world
</template>
<script>
import MainLoader from './rp-main-loader.vue'
import PageLoader from './rp-page-loader.vue'
import PageError from './rp-page-error.vue'
import API from 'API'
const PAGE_PREFIX = 'raith-'
export default {
name : 'rp-pages',
components: {
'main-loader': MainLoader
},
data() {
return {
pages: {
error: null,
data: null
},
activePage: null
}
},
created() {
API.pages().then(resp => { // Load pages
this.pages.data = resp.data
const loading = () => { // Show page from url or default one
this.showPage(window.location.hash.length > 0 ?
window.location.hash.substr(2) :
Object.keys(this.pages.data)[0])
}
this.$nextTick(loading)
window.onhashchange = loading
}).catch(err => {
this.pages.error = err.response.statusText
})
},
computed: {
activeComponent() {
return PAGE_PREFIX + this.activePage
}
},
methods: {
showPage(id) {
const key = PAGE_PREFIX + id
if (!(id in this.pages.data)) {
console.error(`Module not found: ${id}`)
this.$options.components[key] = PageError
return;
}
const mod = this.pages.data[id]
if (!(key in this.$options.components)) { // Must be load
this.$options.components[key] = () => ({
// Dynamicly load component
component: new Promise((resolve, reject) => {
const loaded = () => key in Vue.options.components
const load = () => loaded() ?
resolve(Vue.options.components[key]) : reject()
if (loaded() || document.querySelector('script[src="' + mod.src + '"]')) { //allready loaded
load()
return;
}
const el = document.createElement('script')
el.type = 'text/javascript'
el.async = true
el.src = mod.src
if (mod.integrity != null)
el.integrity = mod.integrity
el.addEventListener('load', load)
el.addEventListener('error', reject)
el.addEventListener('abort', reject)
//setTimeout(() => {
document.head.appendChild(el)
//}, 2000)
}),
loading: PageLoader,
error: PageError,
timeout: 5000
})
}
document.title = `Raith - ${mod.name}`
window.history.pushState({}, document.title, "/#/" + id)
this.activePage = id
}
}
}
</script>

26
compiler/src/test1.vue Normal file
View File

@ -0,0 +1,26 @@
<template lang="pug">
p {{ yolol }}
</template>
<script>
export default {
name: 'raith-test1', //Really important
data() {
return {
yolol: null
}
},
created() {
API.pages().then(resp => {
this.yolol = Object.values(resp.data)[0]
}).catch(err => {
this.yolol = err.response.statusText
})
}
}
</script>
<style lang="sass" scoped>
p
font-style: italic
</style>

21
compiler/src/test2.vue Normal file
View File

@ -0,0 +1,21 @@
<template lang="pug">
p {{ yolo }}
</template>
<script>
export default {
name: 'raith-test2', //Really important
data() {
return {
yolo: null
}
},
created() {
API.pages().then(resp => {
this.yolo = resp.data
}).catch(err => {
this.yolo = err.response.statusText
})
}
}
</script>

124
compiler/webpack.config.js Normal file
View File

@ -0,0 +1,124 @@
// ----------------------------------------------------------------------
// WEBPACK CONFIGURATION
// ----------------------------------------------------------------------
// INSTRUCTIONS
// webpack --env.file="./path/to/file" --relative to the src folder
// Import dependencies
const path = require('path');
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');
const StringReplacePlugin = require('string-replace-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
function resolve(dir) {
return path.resolve(__dirname, dir);
}
module.exports = (env) => {
// Get the basename from the filepath
const filename = path.basename(env.file, '.vue');
const filepath = path.dirname(env.file);
return {
mode : 'production',
entry : {
[filename] : './entry.js'
},
output : {
filename : '[name].js',
path: path.resolve(__dirname, 'dist', filepath)
},
resolve : {
extensions : ['.vue', '.js'],
alias : {
'vue$' : resolve('node_modules/vue/dist/vue.min.js'),
'@' : resolve('src')
}
},
externals : {
vue : 'Vue',
lodash: 'lodash',
API: 'API'
},
module : {
rules : [
{
test : /entry\.js$/,
loader : StringReplacePlugin.replace({
replacements: [
{
pattern: /__FILE__/ig,
replacement: function (match, p1, offset, string) {
return env.file;
}
}
]})
},
{
test : /\.vue$/,
loader : 'vue-loader'
},
{
test : /\.js$/,
loader : 'babel-loader',
include : [
resolve('src')
],
exclude: file => (
/node_modules/.test(file) &&
!/\.vue\.js/.test(file)
)
},
{
test : /\.css$/,
use : [
'vue-style-loader',
'css-loader'
]
},
{
test : /\.less$/,
use : [
'vue-style-loader',
'css-loader',
'less-loader'
]
},
{
test : /\.scss$/,
use : [
'vue-style-loader',
'css-loader',
'sass-loader'
]
},
{
test : /\.sass$/,
use : [
'vue-style-loader',
'css-loader',
{
loader : 'sass-loader',
options : {
indentedSyntax : true
}
}
]
},
{
test: /\.pug$/,
loader: 'pug-plain-loader'
}
]
},
plugins : [
new VueLoaderPlugin(),
new OptimizeCSSPlugin({
cssProcessorOptions: {
safe: true
}
})
]
};
};

View File

@ -5,32 +5,20 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Raith</title>
<link rel="stylesheet" href="style.css">
<script src="lib/lodash.js"></script>
<script src="lib/axios.js"></script>
<script src="lib/API.js"></script>
<script src="lib/vue.full.js"></script>
<script src="compiler/dist/core/rp-pages.js"></script>
</head>
<body>
<div id="app">
<div id="pages-list">
<p v-if="pages.error" style="color: orangered">{{ pages.error }}</p>
<template v-else-if="pages.data">
<template v-for="(page, id) in pages.data">
<button v-if="activePage != id" @click="showPage(id)">{{ page.name }}</button>
<p v-else>{{ page.name }}</p>
</template>
</template>
<p v-else>Loading...</p><!--TODO: Cool loader-->
</div>
<div id="active-page">
<div v-if="activePage">
<keep-alive>
<div :is="activeComponent"></div>
</keep-alive>
</div>
</div>
<p>Hello world</p>
<noscript>Raith client need javascript enabled to work correctly. Sorry</noscript>
<rp-pages></rp-pages>
</div>
<script src="main.js"></script>
<script>
var app = new Vue({
el: '#app'
})
</script>
</body>
</html>

14
lib/API.js Normal file
View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,10 @@
{
"test1": {
"name": "Test1",
"src": "pages/test1/main.js"
"src": "compiler/dist/test1.js"
},
"test2": {
"name": "Test2",
"key": "test2",
"src": "pages/test2/main.js"
"src": "compiler/dist/test2.js"
}
}

View File