diff --git a/modules/client.tsx b/modules/client.tsx index e937ca3..fb7b44c 100644 --- a/modules/client.tsx +++ b/modules/client.tsx @@ -1,30 +1,40 @@ /// import * as React from 'react' +import * as ReactDOM from 'react-dom' import { match, Router, browserHistory } from 'react-router' -import { render } from 'react-dom' -import routes from './routes/RootRoute' +import routes from './routes/Route' import { Promise } from 'es6-promise'; -import * as _ from 'lodash'; -const { pathname, search, hash } = window.location -const location = `${pathname}${search}${hash}` +function timeSince(value: Date): string { + return " [" + ((new Date().getTime() - value.getTime())) + "ms]"; +} -match({ routes, location, history: browserHistory }, (error, redirectLocation, renderProps) => { - if(location == "/about") { - // todo: need a better way to force System.import (async) to trigger - Promise.all( - System.import('./routes/AboutRoute') - ).then(() => { - render( - , - document.getElementById('app') - ) - }); - } else { - render( - , - document.getElementById('app') - ) - } +var time3 = new Date() +match({history: browserHistory, routes}, (err, redirectLocation, renderProps: any) => { + console.log("match:first: " + timeSince(time3)) + const {components} = renderProps; + if(err) console.log("err:" + err); + console.log("redirectLocation:" + redirectLocation); + console.log("renderProps:" + JSON.stringify(renderProps)); + + let router = ( + + ) + + ReactDOM.render(router, document.getElementById('app')); }); + +// browserHistory.listen(location => { +// console.log("browserHistory.listen:location:", location) +// +// setTimeout(function () { +// var time4 = new Date() +// match({history: browserHistory, routes}, (err, redirectLocation, renderProps: any) => { //todo: this is slow +// console.log("match:second: " + timeSince(time4)) +// if(err) console.log("err:" + err); +// console.log("renderProps:" + JSON.stringify(renderProps)); +// }); +// }, 100); +// +// }); diff --git a/modules/components/About.tsx b/modules/components/About.tsx index 48df624..6519a0c 100644 --- a/modules/components/About.tsx +++ b/modules/components/About.tsx @@ -11,6 +11,7 @@ export default class About extends React.Component { with the web inspector open. You should not get the React warning about reusing markup.

+ {this.props.children} ) } diff --git a/modules/components/App.tsx b/modules/components/App.tsx index a79d10f..1cf1999 100644 --- a/modules/components/App.tsx +++ b/modules/components/App.tsx @@ -1,9 +1,15 @@ import * as React from 'react'; +import { browserHistory } from 'react-router' import { Link } from 'react-router' React.isValidElement(null); //needed so React references gets injected on client export default class App extends React.Component { + + drillToItem() { + browserHistory.push("about"); + } + render () { return (
@@ -11,9 +17,13 @@ export default class App extends React.Component {
  • Home
  • About (lazy loaded)
  • +
  • SubAbout (lazy loaded)
  • +
  • this.drillToItem()}>About by history (lazy loaded)
{this.props.children}
); } } + + diff --git a/modules/components/SubAbout.tsx b/modules/components/SubAbout.tsx new file mode 100644 index 0000000..b7789a9 --- /dev/null +++ b/modules/components/SubAbout.tsx @@ -0,0 +1,16 @@ +import * as React from 'react' + +export default class SubAbout extends React.Component { + render() { + return ( +
+

Sub About

+

+ Sub!!! +

+
+ ) + } +} + + diff --git a/modules/routes/AboutRoute.ts b/modules/routes/AboutRoute.ts deleted file mode 100644 index bab342a..0000000 --- a/modules/routes/AboutRoute.ts +++ /dev/null @@ -1,9 +0,0 @@ -import About from '../components/About' - -export default { - path: 'about', - component: About, - onEnter: function enter(nextState, replaceState, callback) { - setTimeout(callback, 1000); - }, -} diff --git a/modules/routes/RootRoute.ts b/modules/routes/Route.ts similarity index 54% rename from modules/routes/RootRoute.ts rename to modules/routes/Route.ts index 4afce7a..07b8335 100644 --- a/modules/routes/RootRoute.ts +++ b/modules/routes/Route.ts @@ -1,40 +1,56 @@ -/// - -// polyfill webpack System.import on NodeJS -if (typeof System === 'undefined') { - var System: ISystemExt = {}; - if (typeof System.import !== 'function') { - System.import = (d) => { - let module = require(d); - return Promise.resolve(module); - } - } -} - -import App from '../components/App' -import Index from '../components/Index' -import {Promise} from 'es6-promise'; - -export default { - path: '/', - component: App, - getChildRoutes(location, cb) { - - //const cached = System.get('./AboutRoute'); //[object Object] is not supported by webpack - //if (cached) callback(null, cached.default); - - Promise.all([ - System.import('./AboutRoute') //webpack 2.0 https://gist.github.com/sokra/27b24881210b56bbaff7 - ]).then(function(modules) { - let module = modules.shift(); - cb(null, [ - module.default - ]) - }).catch(err => { - console.error("getChildRoutes: " + err + " " + err.stack); - }); - }, - indexRoute: { - component: Index - } -} +/// + +// polyfill webpack System.import on NodeJS +if (typeof System === 'undefined') { + var System: ISystemExt = {}; + if (typeof System.import !== 'function') { + System.import = (d) => { + let module = require(d); + return Promise.resolve(module); + } + } +} + +import App from '../components/App' +import Index from '../components/Index' +import {Promise} from 'es6-promise'; + +function timeSince(value: Date): string { + return " [" + ((new Date().getTime() - value.getTime())) + "ms]"; +} + +export default { + path: '/', + component: App, + getChildRoutes(location, cb) { + + console.log("getChildRoutes: START"); + let time1 = new Date(); + + //const cached = System.get('./AboutRoute'); //[object Object] is not supported by webpack + //if (cached) callback(null, cached.default); + + Promise.all([ + System.import('./child/Route') + ]).then(function (modules) { + console.log("getChildRoutes1: " + timeSince(time1)); + let time2 = new Date(); + Promise.all([ + System.import('./child/Route') + ]).then(function (modules) { + console.log("getChildRoutes2: " + timeSince(time2)); + let module = modules.shift(); + cb(null, [ + module.default + ]) + }).catch(err => { + console.error("getChildRoutes: " + err + " " + err.stack); + }); + }).catch(err => { + console.error("getChildRoutes: " + err + " " + err.stack); + }); + }, + indexRoute: { + component: Index + } +} diff --git a/modules/routes/child/Route.ts b/modules/routes/child/Route.ts new file mode 100644 index 0000000..1e25b06 --- /dev/null +++ b/modules/routes/child/Route.ts @@ -0,0 +1,54 @@ +import About from '../../components/About' +import {Promise} from 'es6-promise'; + +function timeSince(value: Date): string { + return " [" + ((new Date().getTime() - value.getTime())) + "ms]"; +} + +function sleep(milliseconds) { + var start = new Date().getTime(); + for (var i = 0; i < 1e7; i++) { + if ((new Date().getTime() - start) > milliseconds){ + break; + } + } +} + +console.log("AboutRoute - sleep") +sleep(400); + +export default { + path: 'about', + component: About, + // onEnter: function enter(nextState, replaceState, callback) { + // setTimeout(callback, 1000); + // }, + getChildRoutes(location, cb) { + + console.log("getChildRoutes: START"); + let time1 = new Date(); + + //const cached = System.get('./AboutRoute'); //[object Object] is not supported by webpack + //if (cached) callback(null, cached.default); + + Promise.all([ + System.import('./child/Route') + ]).then(function (modules) { + console.log("getChildRoutes1: " + timeSince(time1)); + let time2 = new Date(); + Promise.all([ + System.import('./child/Route') + ]).then(function (modules) { + console.log("getChildRoutes2: " + timeSince(time2)); + let module = modules.shift(); + cb(null, [ + module.default + ]) + }).catch(err => { + console.error("getChildRoutes: " + err + " " + err.stack); + }); + }).catch(err => { + console.error("getChildRoutes: " + err + " " + err.stack); + }); + } +} diff --git a/modules/routes/child/child/Route.ts b/modules/routes/child/child/Route.ts new file mode 100644 index 0000000..4429a69 --- /dev/null +++ b/modules/routes/child/child/Route.ts @@ -0,0 +1,21 @@ +import SubAbout from '../../../components/SubAbout' + +function sleep(milliseconds) { + var start = new Date().getTime(); + for (var i = 0; i < 1e7; i++) { + if ((new Date().getTime() - start) > milliseconds){ + break; + } + } +} + +console.log("SubAboutRoute - sleep") +sleep(400); + +export default { + path: 'subabout', + component: SubAbout//, + // onEnter: function enter(nextState, replaceState, callback) { + // setTimeout(callback, 1000); + // }, +} diff --git a/modules/server.tsx b/modules/server.tsx index 188ad55..c28191a 100644 --- a/modules/server.tsx +++ b/modules/server.tsx @@ -6,7 +6,7 @@ import { renderToString } from 'react-dom/server' import { match, RouterContext } from 'react-router' import * as fs from 'fs' import { createPage, write, writeError, writeNotFound, redirect } from './utils/server-utils' -import routes from './routes/RootRoute' +import routes from './routes/Route' import { default as webpackconfig } from "./webpack.config"; import * as webpack from "webpack"; diff --git a/modules/typescript/react-router.d.ts b/modules/typescript/react-router.d.ts index 45a1cac..e287cf9 100644 --- a/modules/typescript/react-router.d.ts +++ b/modules/typescript/react-router.d.ts @@ -1,6 +1,6 @@ -// Compiled using typings@0.6.8 -// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/46719185c564694c5583c4b7ad94dbb786ecad46/react-router/react-router.d.ts -// Type definitions for react-router v1.0.0 +// Compiled using typings@0.6.2 +// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/07feae11780495b90145451d48d4a50923762ef1/react-router/react-router.d.ts +// Type definitions for react-router v2.0.0-rc5 // Project: https://github.com/rackt/react-router // Definitions by: Sergey Buturlakin , Yuichi Murata , Václav Ostrožlík // Definitions: https://github.com/borisyankov/DefinitelyTyped @@ -46,6 +46,7 @@ declare namespace ReactRouter { routeParams?: R routes?: PlainRoute[] children?: React.ReactElement + render?: any //dphack } type RouteComponents = { [key: string]: RouteComponent } @@ -88,6 +89,7 @@ declare namespace ReactRouter { onUpdate?: () => any parseQueryString?: ParseQueryString stringifyQuery?: StringifyQuery + render?: any //dphack } interface Router extends React.ComponentClass {} interface RouterElement extends React.ReactElement {} @@ -111,7 +113,8 @@ declare namespace ReactRouter { interface RouterContextProps extends React.Props { - history: H.History + history?: H.History + router: Router createElement: (component: RouteComponent, props: Object) => any location: H.Location routes: RouteConfig @@ -119,7 +122,11 @@ declare namespace ReactRouter { components?: RouteComponent[] } interface RouterContext extends React.ComponentClass {} - interface RouterContextElement extends React.ReactElement {} + interface RouterContextElement extends React.ReactElement { + history?: H.History + location: H.Location + router?: Router + } const RouterContext: RouterContext @@ -226,7 +233,7 @@ declare namespace ReactRouter { interface MatchArgs { routes?: RouteConfig history?: H.History - location?: any + location?: any //dphack parseQueryString?: ParseQueryString stringifyQuery?: StringifyQuery } @@ -316,7 +323,7 @@ declare module "react-router/lib/useRoutes" { declare module "react-router/lib/PatternUtils" { - export function formatPattern(pattern: string, params: {}): string; + export function formatPattern(pattern: string, params: {}): string; } @@ -372,11 +379,11 @@ declare module "react-router/lib/PropTypes" { } declare module "react-router/lib/browserHistory" { - export default ReactRouter.browserHistory; + export default ReactRouter.browserHistory; } declare module "react-router/lib/hashHistory" { - export default ReactRouter.hashHistory; + export default ReactRouter.hashHistory; } declare module "react-router/lib/match" { @@ -443,6 +450,10 @@ declare module "react-router" { export type RouterState = ReactRouter.RouterState export type HistoryBase = ReactRouter.HistoryBase + + var applyRouterMiddleware: (obj1: any, obj2?: any, obj3?: any) => any; + var withRouter: (obj1: any) => any; + export { Router, Link, @@ -461,7 +472,9 @@ declare module "react-router" { formatPattern, RouterContext, PropTypes, - match + match, + applyRouterMiddleware, + withRouter } export default Router diff --git a/modules/webpack.config.ts b/modules/webpack.config.ts index 4c8266f..7dfcd7e 100644 --- a/modules/webpack.config.ts +++ b/modules/webpack.config.ts @@ -8,10 +8,19 @@ const config: Configuration = { app: [ 'eventsource-polyfill', // necessary for hot reloading with IE 'webpack-hot-middleware/client', + //'babel-polyfill', './modules/client.tsx' ], - vendor: ['react', 'react-dom', 'react-router', 'es6-promise', 'history', - 'babel-regenerator-runtime', 'core-js', 'lodash', 'eventsource-polyfill'] + vendor: [ + 'react', + 'react-dom', + 'react-router', + 'es6-promise', + 'history', + 'core-js', + 'lodash', + 'eventsource-polyfill' + ] }, output: { path: path.resolve("./output/dist/"), @@ -52,8 +61,10 @@ const config: Configuration = { }] }, resolve: { - alias: {}, - extensions: ["", ".js", ".jsx", ".ts", ".tsx"] + alias: { + 'react': path.resolve('./node_modules/react'), //force sub node_modules of node_module to use the primary version of react (eg react-context) + }, + extensions: ["", ".json", ".webpack.js", ".web.js", ".js", ".ts", ".tsx", ".css"] } }; diff --git a/package.json b/package.json index 395fcfc..acd1cc6 100644 --- a/package.json +++ b/package.json @@ -4,27 +4,30 @@ "description": "", "main": "index.js", "dependencies": { - "babel-cli": "^6.4.0", - "babel-core": "^6.4.0", + "babel-cli": "^6.4.5", + "babel-core": "^6.4.5", "babel-loader": "^6.2.1", "babel-polyfill": "^6.5.0", - "babel-preset-es2015": "6.3.x", + "babel-preset-es2015": "^6.3.13", "babel-preset-es2015-webpack": "^6.3.14", - "babel-preset-react": "6.3.x", + "babel-preset-react": "^6.3.13", "es6-promise": "^3.1.2", "eventsource-polyfill": "^0.9.6", "express": "^4.13.4", - "react": "^0.14.6", - "react-dom": "^0.14.6", - "react-router": "^2.0.0", + "history": "^2.1.2", + "react": "^15.1.0", + "react-dom": "^15.1.0", + "react-router": "^2.6.1", "ts-loader": "^0.8.0", - "ts-node": "^0.5.5", + "ts-node": "^1.2.1", "typescript": "^1.8.0", - "webpack": "^2.0.7-beta", + "typings": "^1.3.2", + "webpack": "^2.1.0-beta.20", "webpack-dev-middleware": "^1.5.1", "webpack-hot-middleware": "^2.7.1" }, "scripts": { + "typings:install": "./node_modules/.bin/typings install", "tsc_default": "./node_modules/.bin/tsc --project ./tsconfig.json", "tsc_client": "./node_modules/.bin/tsc --project ./tsconfig-client.json", "start": "node modules/server-boot.js" diff --git a/typings.json b/typings.json index f279c01..5d5111d 100644 --- a/typings.json +++ b/typings.json @@ -1,20 +1,20 @@ { - "ambientDependencies": { + "globalDependencies": { "express": "github:DefinitelyTyped/DefinitelyTyped/express/express.d.ts#dd638012d63e069f2c99d06ef4dcc9616a943ee4", - "history": "github:DefinitelyTyped/DefinitelyTyped/react-router/history.d.ts#46719185c564694c5583c4b7ad94dbb786ecad46", + "history": "github:DefinitelyTyped/DefinitelyTyped/react-router/history.d.ts#f20a05ba43e7c51c0b2c131b561cff65d7a384a0", "lodash": "github:DefinitelyTyped/DefinitelyTyped/lodash/lodash.d.ts#7b7aa2027a8fb6219a8bcf1b6bb12bcd0ff9539d", "mime": "github:DefinitelyTyped/DefinitelyTyped/mime/mime.d.ts#cb5206a8ac1c9a3ddfd126f5ecea6729b2361452", "node": "github:DefinitelyTyped/DefinitelyTyped/node/node.d.ts#20e1eb9616922d382d918cc5a21870a9dbe255f5", - "react": "github:xogeny/DefinitelyTyped/react/react.d.ts#69154f67eeca204d18c7525100d350bba4f21ab1", + "react": "registry:dt/react#0.14.0+20160720060442", "react-addons-create-fragment": "github:DefinitelyTyped/DefinitelyTyped/react/react-addons-create-fragment.d.ts#0bc09e91dd6f2d34b14af4367a138d34f437a5d4", "react-addons-css-transition-group": "github:DefinitelyTyped/DefinitelyTyped/react/react-addons-css-transition-group.d.ts#0bc09e91dd6f2d34b14af4367a138d34f437a5d4", "react-addons-linked-state-mixin": "github:DefinitelyTyped/DefinitelyTyped/react/react-addons-linked-state-mixin.d.ts#0bc09e91dd6f2d34b14af4367a138d34f437a5d4", "react-addons-perf": "github:DefinitelyTyped/DefinitelyTyped/react/react-addons-perf.d.ts#0bc09e91dd6f2d34b14af4367a138d34f437a5d4", "react-addons-pure-render-mixin": "github:DefinitelyTyped/DefinitelyTyped/react/react-addons-pure-render-mixin.d.ts#0bc09e91dd6f2d34b14af4367a138d34f437a5d4", - "react-addons-test-utils": "github:DefinitelyTyped/DefinitelyTyped/react/react-addons-test-utils.d.ts#0bc09e91dd6f2d34b14af4367a138d34f437a5d4", + "react-addons-test-utils": "registry:dt/react-addons-test-utils#0.14.0+20160427035638", "react-addons-transition-group": "github:DefinitelyTyped/DefinitelyTyped/react/react-addons-transition-group.d.ts#0bc09e91dd6f2d34b14af4367a138d34f437a5d4", "react-addons-update": "github:DefinitelyTyped/DefinitelyTyped/react/react-addons-update.d.ts#0bc09e91dd6f2d34b14af4367a138d34f437a5d4", - "react-dom": "github:DefinitelyTyped/DefinitelyTyped/react/react-dom.d.ts#0bc09e91dd6f2d34b14af4367a138d34f437a5d4", + "react-dom": "registry:dt/react-dom#0.14.0+20160412154040", "react-global": "github:DefinitelyTyped/DefinitelyTyped/react/react-global.d.ts#0bc09e91dd6f2d34b14af4367a138d34f437a5d4", "redux-devtools-dock-monitor": "github:DefinitelyTyped/DefinitelyTyped/redux-devtools-dock-monitor/redux-devtools-dock-monitor.d.ts#a507ed9ef2955734b3cf362a0a74b21c7241cebc", "redux-devtools-log-monitor": "github:DefinitelyTyped/DefinitelyTyped/redux-devtools-log-monitor/redux-devtools-log-monitor.d.ts#a507ed9ef2955734b3cf362a0a74b21c7241cebc",