Commit dc0e2fac authored by NGPixel's avatar NGPixel

refactor: client-side optimizations + lazy-loading

parent 6b47064c
...@@ -8,7 +8,7 @@ import Vue from 'vue' ...@@ -8,7 +8,7 @@ import Vue from 'vue'
import VueResource from 'vue-resource' import VueResource from 'vue-resource'
import VueClipboards from 'vue-clipboards' import VueClipboards from 'vue-clipboards'
import store from './store' import store from './store'
import io from 'socket.io-client' import io from 'socket-io-client'
import i18next from 'i18next' import i18next from 'i18next'
import i18nextXHR from 'i18next-xhr-backend' import i18nextXHR from 'i18next-xhr-backend'
import VueI18Next from '@panter/vue-i18next' import VueI18Next from '@panter/vue-i18next'
...@@ -23,14 +23,15 @@ import alertComponent from './components/alert.vue' ...@@ -23,14 +23,15 @@ import alertComponent from './components/alert.vue'
import anchorComponent from './components/anchor.vue' import anchorComponent from './components/anchor.vue'
import colorPickerComponent from './components/color-picker.vue' import colorPickerComponent from './components/color-picker.vue'
import loadingSpinnerComponent from './components/loading-spinner.vue' import loadingSpinnerComponent from './components/loading-spinner.vue'
import modalCreatePageComponent from './components/modal-create-page.vue'
import modalCreateUserComponent from './components/modal-create-user.vue'
import searchComponent from './components/search.vue' import searchComponent from './components/search.vue'
import treeComponent from './components/tree.vue' import treeComponent from './components/tree.vue'
import adminUsersCreateComponent from './modals/admin-users-create.vue'
import adminProfileComponent from './pages/admin-profile.component.js' import adminProfileComponent from './pages/admin-profile.component.js'
import adminSettingsComponent from './pages/admin-settings.component.js' import adminSettingsComponent from './pages/admin-settings.component.js'
import sourceComponent from './pages/source.component.js' import contentViewComponent from './pages/content-view.component.js'
import sourceViewComponent from './pages/source-view.component.js'
// ==================================== // ====================================
// Initialize Vue Modules // Initialize Vue Modules
...@@ -81,12 +82,14 @@ $(() => { ...@@ -81,12 +82,14 @@ $(() => {
alert: alertComponent, alert: alertComponent,
adminProfile: adminProfileComponent, adminProfile: adminProfileComponent,
adminSettings: adminSettingsComponent, adminSettings: adminSettingsComponent,
adminUsersCreate: adminUsersCreateComponent,
anchor: anchorComponent, anchor: anchorComponent,
colorPicker: colorPickerComponent, colorPicker: colorPickerComponent,
contentView: contentViewComponent,
loadingSpinner: loadingSpinnerComponent, loadingSpinner: loadingSpinnerComponent,
modalCreatePage: modalCreatePageComponent,
modalCreateUser: modalCreateUserComponent,
search: searchComponent, search: searchComponent,
sourceView: sourceComponent, sourceView: sourceViewComponent,
tree: treeComponent tree: treeComponent
}, },
store, store,
......
...@@ -14,8 +14,6 @@ ...@@ -14,8 +14,6 @@
</template> </template>
<script> <script>
import * as _ from 'lodash'
export default { export default {
name: 'anchor', name: 'anchor',
data () { data () {
......
...@@ -10,45 +10,44 @@ ...@@ -10,45 +10,44 @@
input.input(type='text', placeholder='page-name', v-model='entrypath', autofocus) input.input(type='text', placeholder='page-name', v-model='entrypath', autofocus)
span.help.is-danger(v-show='isInvalid') This document path is invalid! span.help.is-danger(v-show='isInvalid') This document path is invalid!
footer footer
a.button.is-grey.is-outlined(v-on:click='hide') Discard a.button.is-grey.is-outlined(v-on:click='cancel') Discard
a.button.is-light-blue(v-on:click='create') Create a.button.is-light-blue(v-on:click='create') Create
</template> </template>
<script> <script>
import * as _ from 'lodash' import { isEmpty } from 'lodash'
import { makeSafePath } from '../helpers/pages' // import { makeSafePath } from '../helpers/pages'
import { mapState } from 'vuex'
export default { export default {
name: 'modal-create', name: 'modal-create',
data () { data () {
return { return {
entrypath: '' isLoading: false
isInvalid: false,
isLoading: false,
isShown: false
} }
}, },
computed: mapState('createPage', {
entrypath: '',
isShown: 'shown',
isInvalid: 'invalid'
}),
methods: { methods: {
show: function () { cancel: function () {
this.isInvalid = false this.$store.dispatch('createPageClose')
this.shown = true
},
hide: function () {
this.shown = false
}, },
create: function () { create: function () {
this.isInvalid = false this.isInvalid = false
let newDocPath = makeSafePath(this.entrypath) let newDocPath = makeSafePath(this.entrypath)
if (_.isEmpty(newDocPath)) { if (isEmpty(newDocPath)) {
this.isInvalid = true this.$store.createPage.commit('')
} else { } else {
$('#txt-create-prompt').parent().addClass('is-loading') this.isLoading = true
window.location.assign('/create/' + newDocPath) window.location.assign('/create/' + newDocPath)
} }
} }
}, },
mounted () { mounted () {
this.entrypath = currentBasePath + '/new-page' // this.entrypath = currentBasePath + '/new-page'
} }
} }
</script> </script>
'use strict' 'use strict'
import $ from 'jquery' import $ from 'jquery'
import _ from 'lodash' import delay from 'lodash/delay'
module.exports = { module.exports = {
complete () { complete () {
$('#page-loader').addClass('is-loaded') $('#page-loader').addClass('is-loaded')
_.delay(() => { delay(() => {
$('#page-loader').addClass('is-hidden') $('#page-loader').addClass('is-hidden')
}, 1100) }, 1100)
} }
......
'use strict' 'use strict'
/* eslint-disable no-new */
import $ from 'jquery'
import MathJax from 'mathjax' import MathJax from 'mathjax'
module.exports = (alerts) => { export default {
if ($('#page-type-view').length) { name: 'content-view',
let currentBasePath = ($('#page-type-view').data('entrypath') !== 'home') ? $('#page-type-view').data('entrypath') : '' data() {
return {}
// Copy Path },
mounted() {
// new Vue({
// el: '.modal-copypath',
// render: h => h(CopyPath)
// })
// MathJax Render
MathJax.Hub.Config({ MathJax.Hub.Config({
jax: ['input/TeX', 'input/MathML', 'output/SVG'], jax: ['input/TeX', 'input/MathML', 'output/SVG'],
extensions: ['tex2jax.js', 'mml2jax.js'], extensions: ['tex2jax.js', 'mml2jax.js'],
...@@ -36,8 +26,13 @@ module.exports = (alerts) => { ...@@ -36,8 +26,13 @@ module.exports = (alerts) => {
messageStyle: 'none' messageStyle: 'none'
}) })
MathJax.Hub.Configured() MathJax.Hub.Configured()
require('../modals/create.js')(currentBasePath)
require('../modals/move.js')(currentBasePath, alerts)
} }
} }
// module.exports = (alerts) => {
// if ($('#page-type-view').length) {
// let currentBasePath = ($('#page-type-view').data('entrypath') !== 'home') ? $('#page-type-view').data('entrypath') : ''
// require('../modals/create.js')(currentBasePath)
// require('../modals/move.js')(currentBasePath, alerts)
// }
// }
'use strict' 'use strict'
import * as ace from 'brace' /* global FuseBox */
import 'brace/theme/tomorrow_night'
import 'brace/mode/markdown'
import pageLoader from '../components/page-loader' import pageLoader from '../components/page-loader'
export default { export default {
...@@ -11,8 +10,9 @@ export default { ...@@ -11,8 +10,9 @@ export default {
return {} return {}
}, },
mounted() { mounted() {
FuseBox.import('/js/ace/source-view.js', (ace) => {
let scEditor = ace.edit('source-display') let scEditor = ace.edit('source-display')
scEditor.setTheme('ace/theme/tomorrow_night') scEditor.setTheme('ace/theme/dawn')
scEditor.getSession().setMode('ace/mode/markdown') scEditor.getSession().setMode('ace/mode/markdown')
scEditor.setOption('fontSize', '14px') scEditor.setOption('fontSize', '14px')
scEditor.setOption('hScrollBarAlwaysVisible', false) scEditor.setOption('hScrollBarAlwaysVisible', false)
...@@ -22,5 +22,6 @@ export default { ...@@ -22,5 +22,6 @@ export default {
scEditor.renderer.on('afterRender', () => { scEditor.renderer.on('afterRender', () => {
pageLoader.complete() pageLoader.complete()
}) })
})
} }
} }
...@@ -3,7 +3,8 @@ import Vuex from 'vuex' ...@@ -3,7 +3,8 @@ import Vuex from 'vuex'
import alert from './modules/alert' import alert from './modules/alert'
import anchor from './modules/anchor' import anchor from './modules/anchor'
import adminUsersCreate from './modules/admin-users-create' import modalCreatePage from './modules/modal-create-page'
import modalCreateUser from './modules/modal-create-user'
Vue.use(Vuex) Vue.use(Vuex)
...@@ -22,6 +23,7 @@ export default new Vuex.Store({ ...@@ -22,6 +23,7 @@ export default new Vuex.Store({
modules: { modules: {
alert, alert,
anchor, anchor,
adminUsersCreate modalCreatePage,
modalCreateUser
} }
}) })
'use strict'
export default {
state: {
shown: false
},
getters: {},
mutations: {
shownChange: (state, shownState) => { state.shown = shownState }
},
actions: {
adminUsersCreateOpen({ commit }) { commit('shownChange', true) },
adminUsersCreateClose({ commit }) { commit('shownChange', false) }
}
}
...@@ -13,7 +13,7 @@ const fs = Promise.promisifyAll(require('fs-extra')) ...@@ -13,7 +13,7 @@ const fs = Promise.promisifyAll(require('fs-extra'))
const fsbx = require('fuse-box') const fsbx = require('fuse-box')
const nodemon = require('nodemon') const nodemon = require('nodemon')
const path = require('path') const path = require('path')
const uglify = require('uglify-js') const uglify = require('uglify-es')
// ====================================================== // ======================================================
// Parse cmd arguments // Parse cmd arguments
...@@ -64,13 +64,28 @@ let globalTasks = Promise.mapSeries([ ...@@ -64,13 +64,28 @@ let globalTasks = Promise.mapSeries([
if (err.code === 'ENOENT') { if (err.code === 'ENOENT') {
console.info(colors.white(' └── ') + colors.green('Copy + Minify ACE modes to assets...')) console.info(colors.white(' └── ') + colors.green('Copy + Minify ACE modes to assets...'))
return fs.ensureDirAsync('./assets/js/ace').then(() => { return fs.ensureDirAsync('./assets/js/ace').then(() => {
return fs.readdirAsync('./node_modules/brace/mode').then(modeList => { return Promise.join(
// Core
Promise.all([
fs.readFileAsync('./node_modules/brace/index.js', 'utf8'),
fs.readFileAsync('./node_modules/brace/theme/dawn.js', 'utf8'),
fs.readFileAsync('./node_modules/brace/mode/markdown.js', 'utf8')
]).then(items => {
console.info(colors.white(' source-view.js'))
let result = uglify.minify(items.join(';\n'), { output: { 'max_line_len': 1000000 } })
return fs.writeFileAsync('./assets/js/ace/source-view.js', result.code)
}),
// Modes
fs.readdirAsync('./node_modules/brace/mode').then(modeList => {
return Promise.map(modeList, mdFile => { return Promise.map(modeList, mdFile => {
return fs.readFileAsync(path.join('./node_modules/brace/mode', mdFile), 'utf8').then(modeCode => {
console.info(colors.white(' mode-' + mdFile)) console.info(colors.white(' mode-' + mdFile))
let result = uglify.minify(path.join('./node_modules/brace/mode', mdFile), { output: { 'max_line_len': 1000000 } }) let result = uglify.minify(modeCode, { output: { 'max_line_len': 1000000 } })
return fs.writeFileAsync(path.join('./assets/js/ace', 'mode-' + mdFile), result.code) return fs.writeFileAsync(path.join('./assets/js/ace', 'mode-' + mdFile), result.code)
}) })
}, { concurrency: 3 })
}) })
)
}) })
} else { } else {
throw err throw err
...@@ -179,7 +194,7 @@ let globalTasks = Promise.mapSeries([ ...@@ -179,7 +194,7 @@ let globalTasks = Promise.mapSeries([
const ALIASES = { const ALIASES = {
'brace-ext-modelist': 'brace/ext/modelist.js', 'brace-ext-modelist': 'brace/ext/modelist.js',
'simplemde': 'simplemde/dist/simplemde.min.js', 'simplemde': 'simplemde/dist/simplemde.min.js',
'socket.io-client': 'socket.io-client/dist/socket.io.js', 'socket-io-client': 'socket.io-client/dist/socket.io.js',
'vue': (dev) ? 'vue/dist/vue.js' : 'vue/dist/vue.min.js' 'vue': (dev) ? 'vue/dist/vue.js' : 'vue/dist/vue.min.js'
} }
const SHIMS = { const SHIMS = {
...@@ -209,7 +224,7 @@ globalTasks.then(() => { ...@@ -209,7 +224,7 @@ globalTasks.then(() => {
['.scss', fsbx.SassPlugin({ outputStyle: (dev) ? 'nested' : 'compressed' }), fsbx.CSSPlugin()], ['.scss', fsbx.SassPlugin({ outputStyle: (dev) ? 'nested' : 'compressed' }), fsbx.CSSPlugin()],
fsbx.BabelPlugin({ comments: false, presets: ['es2015'] }), fsbx.BabelPlugin({ comments: false, presets: ['es2015'] }),
fsbx.JSONPlugin(), fsbx.JSONPlugin(),
!dev && fsbx.UglifyJSPlugin({ !dev && fsbx.UglifyESPlugin({
compress: { unused: false }, compress: { unused: false },
output: { 'max_line_len': 1000000 } output: { 'max_line_len': 1000000 }
}) })
...@@ -225,8 +240,8 @@ globalTasks.then(() => { ...@@ -225,8 +240,8 @@ globalTasks.then(() => {
}) })
} }
const bundleLibs = fuse.bundle('libs').instructions('~ index.js') const bundleLibs = fuse.bundle('libs').instructions('~ index.js - brace')
const bundleApp = fuse.bundle('app').instructions('!> index.js') const bundleApp = fuse.bundle('app').instructions('!> [index.js]')
const bundleSetup = fuse.bundle('configure').instructions('> configure.js') const bundleSetup = fuse.bundle('configure').instructions('> configure.js')
switch (mode) { switch (mode) {
......
...@@ -89,8 +89,8 @@ ...@@ -89,8 +89,8 @@
"mime-types": "^2.1.15", "mime-types": "^2.1.15",
"moment": "^2.18.1", "moment": "^2.18.1",
"moment-timezone": "^0.5.13", "moment-timezone": "^0.5.13",
"mongodb": "^2.2.26", "mongodb": "^2.2.27",
"mongoose": "^4.10.0", "mongoose": "^4.10.1",
"multer": "^1.3.0", "multer": "^1.3.0",
"node-graceful": "^0.2.3", "node-graceful": "^0.2.3",
"ora": "^1.2.0", "ora": "^1.2.0",
...@@ -126,7 +126,7 @@ ...@@ -126,7 +126,7 @@
}, },
"devDependencies": { "devDependencies": {
"@glimpse/glimpse": "^0.20.9", "@glimpse/glimpse": "^0.20.9",
"@panter/vue-i18next": "^0.4.1", "@panter/vue-i18next": "^0.5.0",
"babel-cli": "latest", "babel-cli": "latest",
"babel-jest": "latest", "babel-jest": "latest",
"babel-preset-es2015": "latest", "babel-preset-es2015": "latest",
...@@ -147,6 +147,7 @@ ...@@ -147,6 +147,7 @@
"jquery-simple-upload": "^1.0.0", "jquery-simple-upload": "^1.0.0",
"jquery-smooth-scroll": "^2.2.0", "jquery-smooth-scroll": "^2.2.0",
"jquery-sticky": "^1.0.4", "jquery-sticky": "^1.0.4",
"lodash-es": "^4.17.4",
"mathjax": "^2.7.1", "mathjax": "^2.7.1",
"node-sass": "latest", "node-sass": "latest",
"nodemon": "latest", "nodemon": "latest",
...@@ -154,11 +155,11 @@ ...@@ -154,11 +155,11 @@
"snyk": "latest", "snyk": "latest",
"twemoji-awesome": "^1.0.6", "twemoji-awesome": "^1.0.6",
"typescript": "^2.3.2", "typescript": "^2.3.2",
"uglify-js": "latest", "uglify-es": "^3.0.10",
"vee-validate": "^2.0.0-rc.3", "vee-validate": "^2.0.0-rc.3",
"vue": "^2.3.3", "vue": "^2.3.3",
"vue-clipboards": "^1.0.0", "vue-clipboards": "^1.0.0",
"vue-resource": "^1.3.1", "vue-resource": "^1.3.3",
"vue-template-compiler": "^2.3.3", "vue-template-compiler": "^2.3.3",
"vue-template-es2015-compiler": "^1.5.2", "vue-template-es2015-compiler": "^1.5.2",
"vuex": "^2.3.1" "vuex": "^2.3.1"
......
...@@ -31,7 +31,8 @@ block rootNavRight ...@@ -31,7 +31,8 @@ block rootNavRight
block content block content
#page-type-view.page-type-container(data-entrypath=pageData.meta.path) //- #page-type-view.page-type-container(data-entrypath=pageData.meta.path)
content-view(inline-template)
.container.is-fluid.has-mkcontent .container.is-fluid.has-mkcontent
.columns.is-gapless .columns.is-gapless
......
...@@ -2,10 +2,7 @@ extends ../layout.pug ...@@ -2,10 +2,7 @@ extends ../layout.pug
block rootNavCenter block rootNavCenter
block content block content
#page-type-welcome
.container .container
.welcome .welcome
img(src='/images/logo.png', alt='Wiki.js') img(src='/images/logo.png', alt='Wiki.js')
......
This diff was suppressed by a .gitattributes entry.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment