Skip to content

Commit

Permalink
Lazy-load SimpleMDE dependency in MD card (reduces main bundle by 260KB)
Browse files Browse the repository at this point in the history
no issue
- use broccoli-funnel to avoid polluting the `dist/` dir with unused build artefacts
- load codemirror and simplemde CSS up-front to avoid duplicate styles and specificity problems
- pull simplemde dependency out into a separate JS file and lazy-load in `{{gh-simplemde}}` component to reduce main bundle size. Before/after:
  - `vendor.min.js 3.58 MB (795.88 KB gzipped)`
  - `vendor.min.js 3.32 MB (710.66 KB gzipped)`
  • Loading branch information
kevinansfield committed Jan 21, 2019
1 parent c0d9400 commit fdebfae
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 22 deletions.
1 change: 0 additions & 1 deletion app/components/gh-cm-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ const CmEditorComponent = Component.extend({
let loader = this.get('lazyLoader');

yield RSVP.all([
loader.loadStyle('codemirror', 'assets/codemirror/codemirror.css'),
loader.loadScript('codemirror', 'assets/codemirror/codemirror.js')
]);

Expand Down
24 changes: 16 additions & 8 deletions app/components/gh-simplemde.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import config from 'ghost-admin/config/environment';
import {assign} from '@ember/polyfills';
import {computed} from '@ember/object';
import {isEmpty} from '@ember/utils';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency';

export default TextArea.extend({
lazyLoader: service(),

// Public attributes
autofocus: false,
Expand Down Expand Up @@ -60,6 +63,18 @@ export default TextArea.extend({
// instantiate the editor with the contents of value
didInsertElement() {
this._super(...arguments);
this.initSimpleMDE.perform();
},

willDestroyElement() {
this.onEditorDestroy();
this._editor.toTextArea();
delete this._editor;
this._super(...arguments);
},

initSimpleMDE: task(function* () {
yield this.lazyLoader.loadScript('simplemde', 'assets/simplemde/simplemde.js');

let editorOptions = assign(
{element: document.getElementById(this.elementId)},
Expand Down Expand Up @@ -97,12 +112,5 @@ export default TextArea.extend({
}

this.onEditorInit(this._editor);
},

willDestroyElement() {
this.onEditorDestroy();
this._editor.toTextArea();
delete this._editor;
this._super(...arguments);
}
})
});
5 changes: 5 additions & 0 deletions app/styles/layouts/editor.css
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,11 @@
/* SimpleMDE editor
/* ---------------------------------------------------------- */

/* ensure there's no flash of unstyled textarea while initializing */
.gh-markdown-editor textarea {
visibility: hidden;
}

.gh-editor-title {
padding: 0;
}
Expand Down
63 changes: 50 additions & 13 deletions ember-cli-build.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,19 @@ const concat = require('broccoli-concat');
const mergeTrees = require('broccoli-merge-trees');
const uglify = require('broccoli-uglify-sourcemap');
const CleanCSS = require('broccoli-clean-css');
const Funnel = require('broccoli-funnel');
const environment = EmberApp.env();
const isProduction = environment === 'production';
let assetLocation, codemirrorAssets;

assetLocation = function (fileName) {
const assetLocation = function (fileName) {
if (isProduction) {
fileName = fileName.replace('.', '.min.');
}
return `/assets/${fileName}`;
};

codemirrorAssets = function () {
const codemirrorAssets = function () {
let codemirrorFiles = [
// 'lib/codemirror.css',
'theme/xq-light.css',
'lib/codemirror.js',
'mode/htmlmixed/htmlmixed.js',
Expand All @@ -45,23 +44,56 @@ codemirrorAssets = function () {
sourceMapConfig: {enabled: false}
});

let cssTree = concat(tree, {
outputFile: 'assets/codemirror/codemirror.css',
inputFiles: ['**/*.css']
if (isProduction) {
jsTree = uglify(jsTree);
}

let mergedTree = mergeTrees([tree, jsTree]);
return new Funnel(mergedTree, {include: ['assets/**/*', 'theme/**/*']});
}
};

// put the files in vendor ready for importing into the test-support file
if (environment === 'development') {
config.vendor = codemirrorFiles;
}

return config;
};

const simplemdeAssets = function () {
let simplemdeFiles = [
'debug/simplemde.js'
];

if (environment === 'test') {
return {import: simplemdeFiles};
}

let config = {};

config.public = {
include: simplemdeFiles,
destDir: '/',
processTree(tree) {
let jsTree = concat(tree, {
outputFile: 'assets/simplemde/simplemde.js',
inputFiles: ['debug/simplemde.js'],
sourceMapConfig: {enabled: false}
});

if (isProduction) {
jsTree = uglify(jsTree);
cssTree = new CleanCSS(cssTree);
}

return mergeTrees([tree, jsTree, cssTree]);
let mergedTree = mergeTrees([tree, jsTree]);
return new Funnel(mergedTree, {include: ['assets/**/*']});
}
};

// put the files in vendor ready for importing into the test-support file
if (environment === 'development') {
config.vendor = codemirrorFiles;
config.vendor = simplemdeFiles;
}

return config;
Expand Down Expand Up @@ -103,7 +135,8 @@ module.exports = function (defaults) {
}
},
nodeAssets: {
codemirror: codemirrorAssets()
codemirror: codemirrorAssets(),
simplemde: simplemdeAssets()
},
svgJar: {
strategy: 'inline',
Expand All @@ -130,14 +163,17 @@ module.exports = function (defaults) {

// Stop: Normalize
app.import('node_modules/normalize.css/normalize.css');
app.import('node_modules/simplemde/debug/simplemde.css');

// 'dem Styles
// import codemirror + simplemde styles rather than lazy-loading so that
// our overrides work correctly
app.import('node_modules/simplemde/dist/simplemde.min.css');

// 'dem Scripts
app.import('node_modules/google-caja-bower/html-css-sanitizer-bundle.js');
app.import('node_modules/keymaster/keymaster.js');
app.import('node_modules/@tryghost/mobiledoc-kit/dist/amd/mobiledoc-kit.js');
app.import('node_modules/@tryghost/mobiledoc-kit/dist/amd/mobiledoc-kit.map');
app.import('node_modules/simplemde/debug/simplemde.js');
app.import('node_modules/reframe.js/dist/noframe.es.js', {
using: [
{transformation: 'es6', as: 'noframe.js'}
Expand All @@ -148,6 +184,7 @@ module.exports = function (defaults) {
// that tests don't break when running via http://localhost:4200/tests
if (app.env === 'development') {
app.import('vendor/codemirror/lib/codemirror.js', {type: 'test'});
app.import('vendor/simplemde/debug/simplemde.js', {type: 'test'});
}

return app.toTree();
Expand Down

0 comments on commit fdebfae

Please sign in to comment.