Skip to content

Commit

Permalink
Route Based Code Splitting (#265)
Browse files Browse the repository at this point in the history
* feat: adding basic code splitting

* feat: adding app-template, removing dep, adding eslintignore

* feat: adding loading and spinner components, fix test

* fix: dependencies removed

* fix: adjust chunk filenames

* feat: combine chunks based on page routes

* feat: allow splitchunkplugin from config

* fix: condense optimization config

* fix: remove formatting issues

* fix: chunks arr and remove loading component

* fix: remove chunk optimization

* fix: add min content height, stop footer flash

* remove forced formatting

Co-authored-by: Owen Buckley <[email protected]>
  • Loading branch information
hutchgrant and thescientist13 authored Jun 4, 2020
1 parent da25c20 commit 73547bd
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 45 deletions.
14 changes: 13 additions & 1 deletion packages/cli/src/lifecycles/graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ const createGraphFromPages = async (pagesDir, config) => {
// set <title></title> element text, override with markdown title
title = title || '';

// create webpack chunk name based on route and page name
const routes = route.lastIndexOf('/') === route.length - 1 && route.lastIndexOf('/') > 0
? route.substring(1, route.length - 1).split('/')
: route.substring(1, route.length).split('/');
let chunkName = 'page';

routes.forEach(subDir => {
chunkName += '--' + subDir;
});

/*
* Variable Definitions
*----------------------
Expand All @@ -90,6 +100,7 @@ const createGraphFromPages = async (pagesDir, config) => {
* imported into app.js root component
* title: the head <title></title> text
* meta: og graph meta array of objects { property/name, content }
* chunkName: generated chunk name for webpack bundle
*/
const customData = attributes;

Expand Down Expand Up @@ -135,7 +146,8 @@ const createGraphFromPages = async (pagesDir, config) => {
fileName,
relativeExpectedPath,
title,
meta
meta,
chunkName
};
}

Expand Down
28 changes: 10 additions & 18 deletions packages/cli/src/lifecycles/scaffold.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const writePageComponentsFromTemplate = async (compilation) => {
let relPageDir = file.filePath.substring(context.pagesDir.length, file.filePath.length);
let pagePath = '';
const pathLastBackslash = relPageDir.lastIndexOf('/');

pagePath = path.join(context.scratchDir, file.fileName); // non-nested default

if (pathLastBackslash !== 0) {
Expand Down Expand Up @@ -71,30 +71,25 @@ const writePageComponentsFromTemplate = async (compilation) => {

};

const writeListImportFile = async (compilation) => {
const importList = compilation.graph.map(file => {
return `import ${file.relativeExpectedPath};\n`;
});

// Create app directory so that app-template relative imports are correct
const appDir = path.join(compilation.context.scratchDir, 'app');

await fs.ensureDir(appDir);
return await fs.writeFile(path.join(appDir, './list.js'), importList.join(''));
};

const writeRoutes = async(compilation) => {
return new Promise(async (resolve, reject) => {
try {
let data = await fs.readFile(compilation.context.appTemplatePath, 'utf8');

const routes = compilation.graph.map(file => {
return `<lit-route path="${file.route}" component="eve-${file.label}"></lit-route>\n\t\t\t\t`;
return `<lit-route
path="${file.route}"
component="eve-${file.label}"
.resolve="\${() => import(/* webpackChunkName: "${file.chunkName}" */ ${file.relativeExpectedPath})}"
></lit-route>`;
});

const result = data.toString().replace(/MYROUTES/g, routes.join(''));
// Create app directory so that app-template relative imports are correct
const appDir = path.join(compilation.context.scratchDir, 'app');

await fs.writeFile(path.join(compilation.context.scratchDir, 'app', './app.js'), result);
await fs.ensureDir(appDir);
await fs.writeFile(path.join(appDir, './app.js'), result);

resolve();
} catch (err) {
Expand Down Expand Up @@ -127,9 +122,6 @@ module.exports = generateScaffolding = async (compilation) => {
console.log('Generate pages from templates...');
await writePageComponentsFromTemplate(compilation);

console.log('Writing imports for md...');
await writeListImportFile(compilation);

console.log('Writing Lit routes...');
await writeRoutes(compilation);

Expand Down
1 change: 0 additions & 1 deletion packages/cli/src/templates/app-template.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ const store = createStore((state) => state,
);

import '../index/index';
import './list';

connectRouter(store);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ const store = createStore(
compose(lazyReducerEnhancer(combineReducers), applyMiddleware(thunk)));

import '../index/index';
import './list';

connectRouter(store);

Expand Down
117 changes: 117 additions & 0 deletions www/templates/app-template.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { html, css, LitElement } from 'lit-element';
import { connectRouter } from 'lit-redux-router';
import { applyMiddleware, createStore, compose as origCompose, combineReducers } from 'redux';
import { lazyReducerEnhancer } from 'pwa-helpers/lazy-reducer-enhancer.js';
import thunk from 'redux-thunk';
import client from '@greenwood/cli/data/client';
import ConfigQuery from '@greenwood/cli/data/queries/config';
import GraphQuery from '@greenwood/cli/data/queries/graph';
import '../components/header/header';
import '../components/footer/footer';

// eslint-disable-next-line no-underscore-dangle
const compose = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || origCompose;

// eslint-disable-next-line
const store = createStore(
(state, action) => state, // eslint-disable-line
compose(lazyReducerEnhancer(combineReducers), applyMiddleware(thunk)));

import '../index/index';

connectRouter(store);

class AppComponent extends LitElement {

static get styles() {
return css`
.content-outlet {
min-height: 100vh
}`;
}

async connectedCallback() {
super.connectedCallback();
const route = window.location.pathname;
const response = await Promise.all([
await client.query({
query: ConfigQuery
}),
await client.query({
query: GraphQuery
})
]);
const { config } = response[0].data;
const currentPage = response[1].data.graph.filter((page) => {
return route === page.link;
})[0];

const currentPageTitleSuffix = !currentPage || currentPage.link === '/'
? ''
: ` - ${currentPage.title}`;
const fullTitle = `${config.title}${currentPageTitleSuffix}`;

this.setDocumentTitle(fullTitle);
this.setMeta(config.meta, currentPage);
}

setDocumentTitle(title = '') {
const head = document.head;
const titleElement = head.getElementsByTagName('title')[0];

titleElement.innerHTML = title;
}

setMeta(meta = [], currentPage = {}) {
let header = document.head;

meta.forEach(metaItem => {
const metaType = metaItem.rel // type of meta
? 'rel'
: metaItem.name
? 'name'
: 'property';
const metaTypeValue = metaItem[metaType]; // value of the meta
let meta = document.createElement('meta');

if (metaType === 'rel') {
// change to a <link> tag instead
meta = document.createElement('link');

meta.setAttribute('rel', metaTypeValue);
meta.setAttribute('href', metaItem.href);
} else {
const metaContent = metaItem.property === 'og:url'
? `${metaItem.content}${currentPage.link}`
: metaItem.content;

meta.setAttribute(metaType, metaItem[metaType]);
meta.setAttribute('content', metaContent);
}

const oldmeta = header.querySelector(`[${metaType}="${metaTypeValue}"]`);

// rehydration
if (oldmeta) {
header.replaceChild(meta, oldmeta);
} else {
header.appendChild(meta);
}
});
}

render() {
return html`
<div class='wrapper'>
<eve-header></eve-header>
<div class="content-outlet">
MYROUTES
</div>
<lit-route><h1>404 Not found</h1></lit-route>
<eve-footer></eve-footer>
</div>
`;
}
}

customElements.define('eve-app', AppComponent);
4 changes: 0 additions & 4 deletions www/templates/home-template.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,13 @@ class HomeTemplate extends LitElement {
<style>
${homeCss}
</style>
<div class='wrapper'>
<eve-header></eve-header>
<eve-banner></eve-banner>
<div class='content-wrapper'>
<eve-container fluid>
<div class='page-template content single-column'>
<entry></entry>
</div>
</eve-container>
</div>
<eve-footer></eve-footer>
</div>
`;
}
Expand Down
31 changes: 11 additions & 20 deletions www/templates/page-template.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import { html, LitElement } from 'lit-element';
import Prism from 'prismjs'; // eslint-disable-line no-unused-vars
import '../components/header/header';
import '../components/footer/footer';
import '@evergreen-wc/eve-container';
import '../components/shelf/shelf';
import '../components/scroll/scroll';
Expand Down Expand Up @@ -38,25 +35,19 @@ class PageTemplate extends LitElement {
<style>
${pageCss}
</style>
<div class='wrapper'>
<eve-header></eve-header>
<div class='content-wrapper'>
<div class="sidebar">
<eve-shelf .page="${page}"></eve-shelf>
</div>
<div class="content">
<eve-container fluid>
<eve-scroll>
<entry></entry>
</eve-scroll>
</eve-container>
</div>
<div class='content-wrapper'>
<div class="sidebar">
<eve-shelf .page="${page}"></eve-shelf>
</div>
<div class="content">
<eve-container fluid>
<eve-scroll>
<entry></entry>
</eve-scroll>
</eve-container>
</div>
<eve-footer></eve-footer>
</div>
`;
}
Expand Down

0 comments on commit 73547bd

Please sign in to comment.