mirror of
https://github.com/trambarhq/relaks-wordpress-example.git
synced 2025-09-03 05:02:34 +02:00
Loading live data into nav.
This commit is contained in:
12
package-lock.json
generated
12
package-lock.json
generated
@@ -4879,9 +4879,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lodash": {
|
"lodash": {
|
||||||
"version": "4.17.10",
|
"version": "4.17.11",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||||
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==",
|
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"lodash._baseclone": {
|
"lodash._baseclone": {
|
||||||
@@ -5247,6 +5247,12 @@
|
|||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"moment": {
|
||||||
|
"version": "2.23.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.23.0.tgz",
|
||||||
|
"integrity": "sha512-3IE39bHVqFbWWaPOMHZF98Q9c3LDKGTmypMiTM2QygGXXElkFWIH7GxfmlwmY2vwa+wmNsoYZmG2iusf1ZjJoA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"ms": {
|
"ms": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
@@ -29,7 +29,10 @@
|
|||||||
"extract-text-webpack-plugin": "^3.0.2",
|
"extract-text-webpack-plugin": "^3.0.2",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
"html-webpack-plugin": "^2.28.0",
|
"html-webpack-plugin": "^2.28.0",
|
||||||
|
"lodash": "^4.17.11",
|
||||||
|
"moment": "^2.23.0",
|
||||||
"node-sass": "^4.5.3",
|
"node-sass": "^4.5.3",
|
||||||
|
"prop-types": "^15.6.2",
|
||||||
"react": "^16.6.3",
|
"react": "^16.6.3",
|
||||||
"regenerator-runtime": "^0.12.0",
|
"regenerator-runtime": "^0.12.0",
|
||||||
"relaks": "^1.1.7",
|
"relaks": "^1.1.7",
|
||||||
|
15
src/main.js
15
src/main.js
@@ -13,6 +13,10 @@ if (typeof(window) === 'object') {
|
|||||||
async function initialize(evt) {
|
async function initialize(evt) {
|
||||||
// create data source
|
// create data source
|
||||||
let host = `${location.protocol}//${location.host}`;
|
let host = `${location.protocol}//${location.host}`;
|
||||||
|
if (process.env.NODE_ENV !== 'production' && process.env.WEBPACK_DEV_SERVER) {
|
||||||
|
// use hardcoded URL when we're running in dev-server
|
||||||
|
host = 'http://localhost:8000';
|
||||||
|
}
|
||||||
let dataSource = new WordpressDataSource({
|
let dataSource = new WordpressDataSource({
|
||||||
baseURL: `${host}/wp-json`,
|
baseURL: `${host}/wp-json`,
|
||||||
});
|
});
|
||||||
@@ -31,10 +35,13 @@ if (typeof(window) === 'object') {
|
|||||||
if (!appContainer) {
|
if (!appContainer) {
|
||||||
throw new Error('Unable to find app element in DOM');
|
throw new Error('Unable to find app element in DOM');
|
||||||
}
|
}
|
||||||
//let ssrElement = createElement(FrontEnd, { dataSource, routeManager, ssr: 'hydrate' });
|
// expect SSR unless we're running in dev-server
|
||||||
//let seeds = await harvest(ssrElement, { seeds: true });
|
if (!(process.env.NODE_ENV !== 'production' && process.env.WEBPACK_DEV_SERVER)) {
|
||||||
//Relaks.set('seeds', seeds);
|
let ssrElement = createElement(FrontEnd, { dataSource, routeManager, ssr: 'hydrate' });
|
||||||
//hydrate(ssrElement, appContainer);
|
let seeds = await harvest(ssrElement, { seeds: true });
|
||||||
|
Relaks.set('seeds', seeds);
|
||||||
|
hydrate(ssrElement, appContainer);
|
||||||
|
}
|
||||||
|
|
||||||
let appElement = createElement(FrontEnd, { dataSource, routeManager });
|
let appElement = createElement(FrontEnd, { dataSource, routeManager });
|
||||||
render(appElement, appContainer);
|
render(appElement, appContainer);
|
||||||
|
@@ -18,12 +18,6 @@ BODY {
|
|||||||
A {
|
A {
|
||||||
&:link, &:visited {
|
&:link, &:visited {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
color: #f11;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,6 +29,30 @@ A {
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
background-color: #66023c;
|
background-color: #66023c;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
color: #cccccc;
|
||||||
|
|
||||||
|
A {
|
||||||
|
color: #cccccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.archive {
|
||||||
|
LI {
|
||||||
|
margin-top: 0.1em;
|
||||||
|
margin-bottom: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.year {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.months {
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&.collapsed {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-nav {
|
.top-nav {
|
||||||
@@ -44,6 +62,10 @@ A {
|
|||||||
width: calc(100% - 18em);
|
width: calc(100% - 18em);
|
||||||
background-color: #990000; // prevent visual glitch in Android
|
background-color: #990000; // prevent visual glitch in Android
|
||||||
|
|
||||||
|
A {
|
||||||
|
color: #cccccc;
|
||||||
|
}
|
||||||
|
|
||||||
.title-bar {
|
.title-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@@ -1,5 +1,105 @@
|
|||||||
|
import _ from 'lodash';
|
||||||
|
import Moment from 'moment';
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { AsyncComponent } from 'relaks';
|
import { AsyncComponent } from 'relaks';
|
||||||
|
import { Route } from 'routing';
|
||||||
|
import WordPress from 'wordpress';
|
||||||
|
|
||||||
|
class SideNav extends AsyncComponent {
|
||||||
|
static displayName = 'SideNav';
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
let { route } = this.props;
|
||||||
|
let selectedYear;
|
||||||
|
if (route.params.month) {
|
||||||
|
selectedYear = parseInt(route.params.month.substr(0, 4));
|
||||||
|
} else {
|
||||||
|
selectedYear = Moment().year();
|
||||||
|
}
|
||||||
|
this.state = {
|
||||||
|
selectedYear
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async renderAsync(meanwhile) {
|
||||||
|
let { wp, route } = this.props;
|
||||||
|
let { selectedYear } = this.state;
|
||||||
|
let props = {
|
||||||
|
route,
|
||||||
|
selectedYear,
|
||||||
|
onYearSelect: this.handleYearSelect,
|
||||||
|
};
|
||||||
|
meanwhile.delay(50, 50);
|
||||||
|
meanwhile.show(<SideNavSync {...props} />);
|
||||||
|
props.categories = await wp.fetchList('/wp/v2/categories/');
|
||||||
|
meanwhile.show(<SideNavSync {...props} />);
|
||||||
|
|
||||||
|
// get the latest post and the earliest post
|
||||||
|
let latestPosts = await wp.fetchList('/wp/v2/posts/');
|
||||||
|
let latestPost = _.first(latestPosts);
|
||||||
|
let earliestPosts = await wp.fetchList(`/wp/v2/posts/?order=asc&per_page=1`)
|
||||||
|
let earliestPost = _.first(earliestPosts);
|
||||||
|
|
||||||
|
// build the archive tree
|
||||||
|
props.archive = [];
|
||||||
|
if (latestPost && earliestPost) {
|
||||||
|
let lastMonthEnd = Moment(latestPost.date_gmt).endOf('month');
|
||||||
|
let firstMonthStart = Moment(earliestPost.date_gmt).startOf('month');
|
||||||
|
let currentYearEntry;
|
||||||
|
// loop from the last month to the first
|
||||||
|
let e = lastMonthEnd.clone();
|
||||||
|
let s = e.clone().startOf('month');
|
||||||
|
while (s >= firstMonthStart) {
|
||||||
|
let year = s.year();
|
||||||
|
let month = s.month() + 1;
|
||||||
|
if (!currentYearEntry || currentYearEntry.year !== year) {
|
||||||
|
// start a new year
|
||||||
|
currentYearEntry = {
|
||||||
|
year,
|
||||||
|
label: s.format('YYYY'),
|
||||||
|
months: []
|
||||||
|
};
|
||||||
|
props.archive.push(currentYearEntry);
|
||||||
|
}
|
||||||
|
let monthEntry = {
|
||||||
|
month,
|
||||||
|
label: s.format('MMMM'),
|
||||||
|
slug: s.format('YYYY-MM'),
|
||||||
|
post: undefined,
|
||||||
|
start: s.clone(),
|
||||||
|
end: e.clone(),
|
||||||
|
};
|
||||||
|
currentYearEntry.months.push(monthEntry);
|
||||||
|
|
||||||
|
e.subtract(1, 'month');
|
||||||
|
s.subtract(1, 'month');
|
||||||
|
}
|
||||||
|
meanwhile.show(<SideNavSync {...props} />);
|
||||||
|
|
||||||
|
// load the posts of the selected year
|
||||||
|
for (let yearEntry of props.archive) {
|
||||||
|
if (yearEntry.year === selectedYear) {
|
||||||
|
for (let monthEntry of yearEntry.months) {
|
||||||
|
let before = monthEntry.end.toISOString();
|
||||||
|
let after = monthEntry.start.toISOString();
|
||||||
|
let url = `/wp/v2/posts/?before=${before}&after=${after}`;
|
||||||
|
monthEntry.posts = await wp.fetchList(url);
|
||||||
|
|
||||||
|
// force prop change
|
||||||
|
props.archive = _.clone(props.archive);
|
||||||
|
meanwhile.show(<SideNavSync {...props} />);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return <SideNavSync {...props} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleYearSelect = (evt) => {
|
||||||
|
this.setState({ selectedYear: evt.year });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class SideNavSync extends PureComponent {
|
class SideNavSync extends PureComponent {
|
||||||
static displayName = 'SideNavSync';
|
static displayName = 'SideNavSync';
|
||||||
@@ -7,13 +107,128 @@ class SideNavSync extends PureComponent {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="side-nav">
|
<div className="side-nav">
|
||||||
Side-Nav
|
{this.renderCategories()}
|
||||||
|
{this.renderArchive()}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderCategories() {
|
||||||
|
let { categories } = this.props;
|
||||||
|
if (!categories) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// don't show categories with no post
|
||||||
|
categories = _.filter(categories, 'count');
|
||||||
|
// list category with more posts first
|
||||||
|
categories = _.orderBy(categories, [ 'count', 'name' ], [ 'desc', 'asc' ]);
|
||||||
|
return (
|
||||||
|
<ul className="categories">
|
||||||
|
{
|
||||||
|
categories.map((category, i) => {
|
||||||
|
return this.renderCategory(category, i);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderCategory(category, i) {
|
||||||
|
let name = _.get(category, 'name', '');
|
||||||
|
let description = _.get(category, 'description', '');
|
||||||
|
let slug = _.get(category, 'slug', '');
|
||||||
|
let url = '';
|
||||||
|
return (
|
||||||
|
<li key={i}>
|
||||||
|
<a href={url} title={description}>{name}</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderArchive() {
|
||||||
|
let { archive } = this.props;
|
||||||
|
if (!archive) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<ul className="archive">
|
||||||
|
{
|
||||||
|
archive.map((entry, i) => {
|
||||||
|
return this.renderYear(entry, i);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderYear(yearEntry, i) {
|
||||||
|
let { selectedYear } = this.props;
|
||||||
|
let labelClass = 'year';
|
||||||
|
let listClass = 'months';
|
||||||
|
if (yearEntry.year === selectedYear) {
|
||||||
|
labelClass += ' selected';
|
||||||
|
} else {
|
||||||
|
listClass += ' collapsed';
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<li key={i}>
|
||||||
|
<span className={labelClass} data-year={yearEntry.year} onClick={this.handleYearClick}>
|
||||||
|
{yearEntry.label}
|
||||||
|
</span>
|
||||||
|
<ul className={listClass}>
|
||||||
|
{
|
||||||
|
yearEntry.months.map((entry, i) => {
|
||||||
|
return this.renderMonth(entry, i);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderMonth(monthEntry, i) {
|
||||||
|
let url;
|
||||||
|
if (!_.isEmpty(monthEntry.posts) || _.isUndefined(monthEntry.posts)) {
|
||||||
|
url = '#';
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<li key={i}>
|
||||||
|
<a href={url}>{monthEntry.label}</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleYearClick = (evt) => {
|
||||||
|
let { onYearSelect } = this.props;
|
||||||
|
let year = parseInt(evt.currentTarget.getAttribute('data-year'));
|
||||||
|
if (onYearSelect) {
|
||||||
|
onYearSelect({
|
||||||
|
type: 'yearselect',
|
||||||
|
target: this,
|
||||||
|
year,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
const PropTypes = require('prop-types');
|
||||||
|
|
||||||
|
SideNav.propTypes = {
|
||||||
|
wp: PropTypes.instanceOf(WordPress).isRequired,
|
||||||
|
route: PropTypes.instanceOf(Route).isRequired,
|
||||||
|
};
|
||||||
|
SideNavSync.propTypes = {
|
||||||
|
categories: PropTypes.arrayOf(PropTypes.object),
|
||||||
|
archive: PropTypes.arrayOf(PropTypes.object),
|
||||||
|
selectedYear: PropTypes.number,
|
||||||
|
route: PropTypes.instanceOf(Route),
|
||||||
|
onYearSelect: PropTypes.func,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
SideNavSync as default,
|
SideNav as default,
|
||||||
|
SideNav,
|
||||||
SideNavSync,
|
SideNavSync,
|
||||||
};
|
};
|
||||||
|
@@ -1,12 +1,32 @@
|
|||||||
|
import _ from 'lodash';
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { AsyncComponent } from 'relaks';
|
import { AsyncComponent } from 'relaks';
|
||||||
|
import { Route } from 'routing';
|
||||||
|
import WordPress from 'wordpress';
|
||||||
|
|
||||||
class TopBarSync extends PureComponent {
|
class TopNav extends AsyncComponent {
|
||||||
|
static displayName = 'TopNav';
|
||||||
|
|
||||||
|
async renderAsync(meanwhile) {
|
||||||
|
let { wp, route } = this.props;
|
||||||
|
let props = {
|
||||||
|
route,
|
||||||
|
};
|
||||||
|
meanwhile.show(<TopNavSync {...props} />);
|
||||||
|
props.system = await wp.fetchOne('/');
|
||||||
|
meanwhile.show(<TopNavSync {...props} />);
|
||||||
|
props.pages = await wp.fetchList('/wp/v2/pages/');
|
||||||
|
return <TopNavSync {...props} />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TopNavSync extends PureComponent {
|
||||||
static displayName = 'TopNavSync';
|
static displayName = 'TopNavSync';
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
let { onMouseOver, onMouseOut } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className="top-nav">
|
<div className="top-nav" onMouseOver={onMouseOver} onMouseOut={onMouseOut}>
|
||||||
{this.renderTitleBar()}
|
{this.renderTitleBar()}
|
||||||
{this.renderPageLinkBar()}
|
{this.renderPageLinkBar()}
|
||||||
{this.renderSearchBar()}
|
{this.renderSearchBar()}
|
||||||
@@ -15,34 +35,52 @@ class TopBarSync extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderTitleBar() {
|
renderTitleBar() {
|
||||||
|
let { system } = this.props;
|
||||||
|
let name = _.get(system, 'name', '');
|
||||||
|
let description = _.get(system, 'description', '');
|
||||||
return (
|
return (
|
||||||
<div className="title-bar">
|
<div className="title-bar">
|
||||||
<div className="title">
|
<div className="title" title={description}>
|
||||||
<i className="fa fa-home" />
|
<i className="fa fa-home" />
|
||||||
<span className="site-name">Romanes eunt domus</span>
|
<span className="site-name">{name}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderPageLinkBar() {
|
renderPageLinkBar() {
|
||||||
|
let { pages } = this.props;
|
||||||
|
pages = _.sortBy(pages, 'menu_order');
|
||||||
return (
|
return (
|
||||||
<div className="page-bar">
|
<div className="page-bar">
|
||||||
<div className="button">
|
{
|
||||||
Hello
|
pages.map((page, i) => {
|
||||||
</div>
|
return this.renderPageLinkButton(page, i);
|
||||||
<div className="button">
|
})
|
||||||
World
|
}
|
||||||
</div>
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderPageLinkButton(page, i) {
|
||||||
|
let { route } = this.props;
|
||||||
|
let title = _.get(page, 'title.rendered');
|
||||||
|
let slug = _.get(page, 'slug');
|
||||||
|
let url = '';
|
||||||
|
return (
|
||||||
|
<div className="button" key={i}>
|
||||||
|
<a href={url}>{title}</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSearchBar() {
|
renderSearchBar() {
|
||||||
|
let { route } = this.props;
|
||||||
|
let search = _.get(route.params, 'search', '');
|
||||||
return (
|
return (
|
||||||
<div className="search-bar">
|
<div className="search-bar">
|
||||||
<span className="input-container">
|
<span className="input-container">
|
||||||
<input type="text" value="Hello" />
|
<input type="text" value={search} />
|
||||||
<i className="fa fa-search" />
|
<i className="fa fa-search" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -50,7 +88,28 @@ class TopBarSync extends PureComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
TopNavSync.defaultProps = {
|
||||||
TopBarSync as default,
|
system: {},
|
||||||
TopBarSync,
|
pages: [],
|
||||||
|
search: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
const PropTypes = require('prop-types');
|
||||||
|
|
||||||
|
TopNav.propTypes = {
|
||||||
|
wp: PropTypes.instanceOf(WordPress).isRequired,
|
||||||
|
route: PropTypes.instanceOf(Route).isRequired,
|
||||||
|
};
|
||||||
|
TopNavSync.propTypes = {
|
||||||
|
system: PropTypes.object,
|
||||||
|
pages: PropTypes.arrayOf(PropTypes.object),
|
||||||
|
route: PropTypes.instanceOf(Route).isRequired,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
TopNav as default,
|
||||||
|
TopNav,
|
||||||
|
TopNavSync,
|
||||||
};
|
};
|
||||||
|
@@ -57,26 +57,9 @@ var clientConfig = {
|
|||||||
analyzerMode: (event === 'build') ? 'static' : 'disabled',
|
analyzerMode: (event === 'build') ? 'static' : 'disabled',
|
||||||
reportFilename: `report.html`,
|
reportFilename: `report.html`,
|
||||||
}),
|
}),
|
||||||
new HtmlWebpackPlugin({
|
|
||||||
template: Path.resolve(`./src/index.html`),
|
|
||||||
filename: Path.resolve(`./server/www/index.html`),
|
|
||||||
}),
|
|
||||||
new ExtractTextPlugin("styles.css"),
|
new ExtractTextPlugin("styles.css"),
|
||||||
],
|
],
|
||||||
devtool: (event === 'build') ? false : 'inline-source-map',
|
devtool: (event === 'build') ? false : 'inline-source-map',
|
||||||
devServer: {
|
|
||||||
inline: true,
|
|
||||||
historyApiFallback: {
|
|
||||||
rewrites: [
|
|
||||||
{
|
|
||||||
from: /.*/,
|
|
||||||
to: function(context) {
|
|
||||||
return context.parsedUrl.pathname.replace(/.*\/(.*)$/, '/$1');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var serverConfig = {
|
var serverConfig = {
|
||||||
@@ -102,7 +85,39 @@ var serverConfig = {
|
|||||||
devtool: clientConfig.devtool,
|
devtool: clientConfig.devtool,
|
||||||
};
|
};
|
||||||
|
|
||||||
var configs = module.exports = clientConfig; //[ clientConfig, serverConfig ];
|
var configs = module.exports = [ clientConfig, serverConfig ];
|
||||||
|
|
||||||
|
var isDevServer = process.argv.find((arg) => {
|
||||||
|
return arg.includes('webpack-dev-server') ;
|
||||||
|
});
|
||||||
|
if (isDevServer) {
|
||||||
|
// remove server config
|
||||||
|
configs.pop();
|
||||||
|
// need HTML page
|
||||||
|
clientConfig.plugins.push(new HtmlWebpackPlugin({
|
||||||
|
template: Path.resolve(`./src/index.html`),
|
||||||
|
filename: Path.resolve(`./server/www/index.html`),
|
||||||
|
}));
|
||||||
|
// set constant
|
||||||
|
var constants = {
|
||||||
|
'process.env.WEBPACK_DEV_SERVER': 'true',
|
||||||
|
};
|
||||||
|
clientConfig.plugins.unshift(new DefinePlugin(constants));
|
||||||
|
// config dev-server to support client-side routing
|
||||||
|
clientConfig.devServer = {
|
||||||
|
inline: true,
|
||||||
|
historyApiFallback: {
|
||||||
|
rewrites: [
|
||||||
|
{
|
||||||
|
from: /.*/,
|
||||||
|
to: function(context) {
|
||||||
|
return context.parsedUrl.pathname.replace(/.*\/(.*)$/, '/$1');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
var constants = {};
|
var constants = {};
|
||||||
if (event === 'build') {
|
if (event === 'build') {
|
||||||
@@ -110,14 +125,13 @@ if (event === 'build') {
|
|||||||
|
|
||||||
configs.forEach((config) => {
|
configs.forEach((config) => {
|
||||||
// set NODE_ENV to production
|
// set NODE_ENV to production
|
||||||
var plugins = config.plugins;
|
|
||||||
var constants = {
|
var constants = {
|
||||||
'process.env.NODE_ENV': '"production"',
|
'process.env.NODE_ENV': '"production"',
|
||||||
};
|
};
|
||||||
plugins.unshift(new DefinePlugin(constants));
|
config.plugins.unshift(new DefinePlugin(constants));
|
||||||
|
|
||||||
// use Uglify to remove dead-code
|
// use Uglify to remove dead-code
|
||||||
plugins.unshift(new UglifyJSPlugin({
|
config.plugins.unshift(new UglifyJSPlugin({
|
||||||
uglifyOptions: {
|
uglifyOptions: {
|
||||||
compress: {
|
compress: {
|
||||||
drop_console: true,
|
drop_console: true,
|
||||||
|
Reference in New Issue
Block a user