diff --git a/samples/react/MusicStore/.gitignore b/samples/react/MusicStore/.gitignore index bca785d..8d1beeb 100644 --- a/samples/react/MusicStore/.gitignore +++ b/samples/react/MusicStore/.gitignore @@ -1,3 +1,4 @@ music-db.sqlite /wwwroot/dist/ /node_modules/ +yarn.lock diff --git a/samples/react/MusicStore/ReactApp/boot-server.tsx b/samples/react/MusicStore/ReactApp/boot-server.tsx index 4bf5d6e..7aaa1f1 100644 --- a/samples/react/MusicStore/ReactApp/boot-server.tsx +++ b/samples/react/MusicStore/ReactApp/boot-server.tsx @@ -5,19 +5,29 @@ import { match, RouterContext } from 'react-router'; import createMemoryHistory from 'history/lib/createMemoryHistory'; import { routes } from './routes'; import configureStore from './configureStore'; -React; +type BootResult = { html?: string, globals?: { [key: string]: any }, redirectUrl?: string}; export default function (params: any): Promise<{ html: string }> { - return new Promise<{ html: string, globals: { [key: string]: any } }>((resolve, reject) => { + return new Promise((resolve, reject) => { // Match the incoming request against the list of client-side routes match({ routes, location: params.location }, (error, redirectLocation, renderProps: any) => { if (error) { throw error; } + // If there's a redirection, just send this information back to the host application + if (redirectLocation) { + resolve({ redirectUrl: redirectLocation.pathname }); + return; + } + + // If it didn't match any route, renderProps will be undefined + if (!renderProps) { + throw new Error(`The location '${ params.url }' doesn't match any route configured in react-router.`); + } + // Build an instance of the application - const history = createMemoryHistory(params.url); - const store = configureStore(history); + const store = configureStore(); const app = ( diff --git a/samples/react/MusicStore/ReactApp/boot.tsx b/samples/react/MusicStore/ReactApp/boot.tsx index ad8f367..ea3807d 100644 --- a/samples/react/MusicStore/ReactApp/boot.tsx +++ b/samples/react/MusicStore/ReactApp/boot.tsx @@ -1,21 +1,25 @@ +import './styles/styles.css'; +import 'bootstrap/dist/css/bootstrap.css'; + import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { browserHistory, Router } from 'react-router'; import { Provider } from 'react-redux'; -React; // Need this reference otherwise TypeScript doesn't think we're using it and ignores the import - -import './styles/styles.css'; -import 'bootstrap/dist/css/bootstrap.css'; -import configureStore from './configureStore'; +import { syncHistoryWithStore } from 'react-router-redux'; import { routes } from './routes'; +import configureStore from './configureStore'; import { ApplicationState } from './store'; +// Get the application-wide store instance, prepopulating with state from the server where available. const initialState = (window as any).initialReduxState as ApplicationState; -const store = configureStore(browserHistory, initialState); +const store = configureStore(initialState); +const history = syncHistoryWithStore(browserHistory, store); +// This code starts up the React app when it runs in a browser. It sets up the routing configuration +// and injects the app into a DOM element. ReactDOM.render( - + , document.getElementById('react-app') ); diff --git a/samples/react/MusicStore/ReactApp/configureStore.ts b/samples/react/MusicStore/ReactApp/configureStore.ts index 9274c22..b778845 100644 --- a/samples/react/MusicStore/ReactApp/configureStore.ts +++ b/samples/react/MusicStore/ReactApp/configureStore.ts @@ -1,28 +1,22 @@ -import { createStore, applyMiddleware, compose, combineReducers } from 'redux'; -import * as thunkModule from 'redux-thunk'; -import { syncHistory, routeReducer } from 'react-router-redux'; +import { createStore, applyMiddleware, compose, combineReducers, GenericStoreEnhancer } from 'redux'; +import thunk from 'redux-thunk'; +import { routerReducer } from 'react-router-redux'; import * as Store from './store'; import { typedToPlain } from 'redux-typed'; -export default function configureStore(history: HistoryModule.History, initialState?: Store.ApplicationState) { - // Build middleware - const thunk = (thunkModule as any).default; // Workaround for TypeScript not importing thunk module as expected - const reduxRouterMiddleware = syncHistory(history); - const middlewares = [thunk, reduxRouterMiddleware, typedToPlain]; - const devToolsExtension = null;//(window as any).devToolsExtension; // If devTools is installed, connect to it - - const finalCreateStore = compose( - applyMiddleware(...middlewares), +export default function configureStore(initialState?: Store.ApplicationState) { + // Build middleware. These are functions that can process the actions before they reach the store. + const windowIfDefined = typeof window === 'undefined' ? null : window as any; + // If devTools is installed, connect to it + const devToolsExtension = windowIfDefined && windowIfDefined.devToolsExtension as () => GenericStoreEnhancer; + const createStoreWithMiddleware = compose( + applyMiddleware(thunk, typedToPlain), devToolsExtension ? devToolsExtension() : f => f - )(createStore) + )(createStore); - // Combine all reducers + // Combine all reducers and instantiate the app-wide store instance const allReducers = buildRootReducer(Store.reducers); - - const store = finalCreateStore(allReducers, initialState) as Redux.Store; - - // Required for replaying actions from devtools to work - reduxRouterMiddleware.listenForReplays(store); + const store = createStoreWithMiddleware(allReducers, initialState) as Redux.Store; // Enable Webpack hot module replacement for reducers if (module.hot) { @@ -36,5 +30,5 @@ export default function configureStore(history: HistoryModule.History, initialSt } function buildRootReducer(allReducers) { - return combineReducers(Object.assign({}, allReducers, { routing: routeReducer })) as Redux.Reducer; + return combineReducers(Object.assign({}, allReducers, { routing: routerReducer })); } diff --git a/samples/react/MusicStore/package.json b/samples/react/MusicStore/package.json index 084f8ee..9d0a7cc 100644 --- a/samples/react/MusicStore/package.json +++ b/samples/react/MusicStore/package.json @@ -1,45 +1,52 @@ { - "name": "MusicStore", + "name": "music-store", "version": "0.0.0", - "devDependencies": { - "babel-loader": "^6.2.1", - "babel-plugin-react-transform": "^2.0.0", - "babel-preset-es2015": "^6.3.13", - "babel-preset-react": "^6.3.13", + "dependencies": { + "@types/react": "^0.14.29", + "@types/react-bootstrap": "^0.0.35", + "@types/react-dom": "^0.14.14", + "@types/react-redux": "^4.4.29", + "@types/react-router": "^2.0.30", + "@types/react-router-bootstrap": "^0.0.27", + "@types/react-router-redux": "^4.0.30", + "@types/redux": "3.5.27", + "@types/redux-thunk": "^2.1.28", + "@types/source-map": "^0.1.28", + "@types/uglify-js": "^2.0.27", + "@types/webpack": "^1.12.35", + "@types/webpack-env": "^1.12.1", + "@types/whatwg-fetch": "0.0.28", + "aspnet-prerendering": "^1.0.7", + "aspnet-webpack": "^1.0.17", + "aspnet-webpack-react": "^1.0.2", + "babel-core": "^6.5.2", + "babel-loader": "^6.2.3", + "babel-preset-es2015": "^6.5.0", + "babel-preset-react": "^6.5.0", + "bootstrap": "^3.3.6", "css-loader": "^0.23.1", - "express": "^4.13.4", + "domain-task": "^2.0.1", + "event-source-polyfill": "^0.0.7", "extract-text-webpack-plugin": "^1.0.1", "file-loader": "^0.8.5", - "react-transform-hmr": "^1.0.2", + "jquery": "^2.2.1", + "react": "^15.3.2", + "react-bootstrap": "^0.30.6", + "react-dom": "^15.3.2", + "react-redux": "^4.4.5", + "react-router": "^2.8.1", + "react-router-bootstrap": "^0.23.1", + "react-router-redux": "^4.0.6", + "redux": "^3.6.0", + "redux-thunk": "^2.1.0", + "redux-typed": "^2.0.0", "style-loader": "^0.13.0", - "ts-loader": "^0.8.0", - "typescript": "^1.7.5", + "ts-loader": "^0.8.1", + "typescript": "2.0.3", "url-loader": "^0.5.7", - "webpack": "^1.12.12", - "webpack-dev-middleware": "^1.5.1", - "webpack-hot-middleware": "^2.6.4" - }, - "dependencies": { - "aspnet-prerendering": "^1.0.0", - "aspnet-webpack": "^1.0.3", - "aspnet-webpack-react": "^1.0.1", - "bootstrap": "^3.3.6", - "domain-context": "^0.5.1", - "domain-task": "^2.0.0", - "history": "^2.0.0", - "isomorphic-fetch": "^2.2.1", - "memory-fs": "^0.3.0", - "react": "^0.14.7", - "react-bootstrap": "^0.28.2", - "react-dom": "^0.14.7", - "react-redux": "^4.2.1", - "react-router": "^2.0.0-rc5", - "react-router-bootstrap": "^0.20.1", - "react-router-redux": "^2.1.0", - "redux": "^3.2.1", - "redux-thunk": "^1.0.3", - "redux-typed": "^1.0.0", - "require-from-string": "^1.1.0", - "webpack-externals-plugin": "^1.0.0" + "webpack": "^1.13.2", + "webpack-hot-middleware": "^2.12.2", + "webpack-merge": "^0.14.1", + "webpack-node-externals": "^1.4.3" } } diff --git a/samples/react/MusicStore/project.json b/samples/react/MusicStore/project.json index 6f5c801..423d313 100755 --- a/samples/react/MusicStore/project.json +++ b/samples/react/MusicStore/project.json @@ -1,56 +1,83 @@ { - "version": "1.0.0-*", - "buildOptions": { - "emitEntryPoint": true, - "preserveCompilationContext": true - }, - "runtimeOptions": { - "gcServer": true - }, - "tooling": { - "defaultNamespace": "MusicStore" - }, - -"dependencies": { + "dependencies": { "Microsoft.NETCore.App": { - "version": "1.0.0", + "version": "1.0.1", "type": "platform" }, + "Microsoft.AspNetCore.ReactServices": "1.0.0-*", "Microsoft.AspNetCore.Diagnostics": "1.0.0", "Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0", + "Microsoft.AspNetCore.Mvc": "1.0.1", + "Microsoft.AspNetCore.Razor.Tools": { + "version": "1.0.0-preview2-final", + "type": "build" + }, "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0", - "Microsoft.AspNetCore.Mvc": "1.0.0", - "Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.0", - "Microsoft.AspNetCore.Server.Kestrel": "1.0.0", + "Microsoft.AspNetCore.Server.Kestrel": "1.0.1", "Microsoft.AspNetCore.StaticFiles": "1.0.0", - "Microsoft.Extensions.Configuration.Json": "1.0.0", - "Microsoft.Extensions.Logging.Console": "1.0.0", - "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.Extensions.Logging.Debug": "1.0.0", "Microsoft.EntityFrameworkCore.SQLite": "1.0.0", - "Microsoft.AspNetCore.ReactServices": "1.0.0-*", - "AutoMapper": "5.0.2" + "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0", + "Microsoft.Extensions.Configuration.Json": "1.0.0", + "Microsoft.Extensions.Configuration.CommandLine": "1.0.0", + "Microsoft.Extensions.Logging": "1.0.0", + "Microsoft.Extensions.Logging.Console": "1.0.0", + "Microsoft.Extensions.Logging.Debug": "1.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0", + "AutoMapper": "5.0.2" }, + + "tools": { + "Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final", + "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final", + "Microsoft.DotNet.Watcher.Tools": "1.0.0-preview2-final" + }, + "frameworks": { "netcoreapp1.0": { "imports": [ "dotnet5.6", - "dnxcore50", "portable-net45+win8" ] } }, + + "buildOptions": { + "emitEntryPoint": true, + "preserveCompilationContext": true, + "compile": { + "exclude": ["node_modules"] + } + }, + + "runtimeOptions": { + "configProperties": { + "System.GC.Server": true + } + }, + "publishOptions": { - "exclude": [ + "include": [ + "appsettings.json", + "ClientApp/dist", "node_modules", - "bower_components", - "**.xproj", - "**.user", - "**.vspscc" + "Views", + "web.config", + "wwwroot" + ], + "exclude": [ + "wwwroot/dist/*.map" ] }, + "scripts": { - "prepublish": [ "npm install" ], + "prepublish": [ + "npm install", + "node node_modules/webpack/bin/webpack.js" + ], "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ] + }, + + "tooling": { + "defaultNamespace": "MusicStore" } } diff --git a/samples/react/MusicStore/tsconfig.json b/samples/react/MusicStore/tsconfig.json index 863f693..f5bad2c 100644 --- a/samples/react/MusicStore/tsconfig.json +++ b/samples/react/MusicStore/tsconfig.json @@ -4,7 +4,8 @@ "target": "es6", "jsx": "preserve", "sourceMap": true, - "experimentalDecorators": true + "experimentalDecorators": true, + "types": [ "webpack-env", "whatwg-fetch" ] }, "exclude": [ "node_modules" diff --git a/samples/react/MusicStore/tsd.json b/samples/react/MusicStore/tsd.json deleted file mode 100644 index cebcea0..0000000 --- a/samples/react/MusicStore/tsd.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "version": "v4", - "repo": "borisyankov/DefinitelyTyped", - "ref": "master", - "path": "typings", - "bundle": "typings/tsd.d.ts", - "installed": { - "react/react.d.ts": { - "commit": "e69fe60f2d6377ea4fae539493997b098f52cad1" - }, - "react/react-dom.d.ts": { - "commit": "86dbea8fc37d9473fee465da4f0a21bea4f8cbd9" - }, - "redux/redux.d.ts": { - "commit": "e69fe60f2d6377ea4fae539493997b098f52cad1" - }, - "webpack/webpack-env.d.ts": { - "commit": "717a5fdb079f8dd7c19f1b22f7f656dd990f0ccf" - }, - "react-redux/react-redux.d.ts": { - "commit": "717a5fdb079f8dd7c19f1b22f7f656dd990f0ccf" - }, - "react-bootstrap/react-bootstrap.d.ts": { - "commit": "e69fe60f2d6377ea4fae539493997b098f52cad1" - }, - "react-router/react-router.d.ts": { - "commit": "e69fe60f2d6377ea4fae539493997b098f52cad1" - }, - "react-router/history.d.ts": { - "commit": "e69fe60f2d6377ea4fae539493997b098f52cad1" - }, - "react-router-bootstrap/react-router-bootstrap.d.ts": { - "commit": "e69fe60f2d6377ea4fae539493997b098f52cad1" - }, - "react-router-redux/react-router-redux.d.ts": { - "commit": "e69fe60f2d6377ea4fae539493997b098f52cad1" - }, - "redux-thunk/redux-thunk.d.ts": { - "commit": "e69fe60f2d6377ea4fae539493997b098f52cad1" - }, - "whatwg-fetch/whatwg-fetch.d.ts": { - "commit": "f4b1797c1201b6c575668f5d7ea12d9b1ab21846" - } - } -} diff --git a/samples/react/MusicStore/typings/react-bootstrap/react-bootstrap.d.ts b/samples/react/MusicStore/typings/react-bootstrap/react-bootstrap.d.ts deleted file mode 100644 index c6e30d0..0000000 --- a/samples/react/MusicStore/typings/react-bootstrap/react-bootstrap.d.ts +++ /dev/null @@ -1,976 +0,0 @@ -// Type definitions for react-bootstrap -// Project: https://github.com/react-bootstrap/react-bootstrap -// Definitions by: Walker Burgin -// Definitions: https://github.com/borisyankov/DefinitelyTyped - -/// - -declare module "react-bootstrap" { - // Import React - import React = require("react"); - - - //