diff --git a/.gitignore b/.gitignore
index d00c2d9752..35660fefec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ database.sqlite
node_modules
ncp-debug.log
npm-debug.log
+stats.json
diff --git a/Dockerfile b/Dockerfile
index 8c7c90c7e7..707ebe8240 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,10 +1,11 @@
-FROM node:7.2.1-alpine
+FROM node:6.9.5-alpine
# Copy application files
COPY ./build /usr/src/app
WORKDIR /usr/src/app
-# Install Node.js dependencies
-RUN npm install --production --silent
+# Install Yarn and Node.js dependencies
+RUN npm install yarn --global --no-progress --silent --depth 0 && \
+ yarn install --production --no-progress
CMD [ "node", "server.js" ]
diff --git a/LICENSE.txt b/LICENSE.txt
index 16f8127007..3e95f03c67 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,6 +1,6 @@
The MIT License
-Copyright (c) 2014-2016 Konstantin Tarkus, KriaSoft LLC.
+Copyright (c) 2014-present Konstantin Tarkus, KriaSoft LLC.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index e377181272..9d1ef8748e 100644
--- a/README.md
+++ b/README.md
@@ -22,9 +22,7 @@ and newcomers to the industry.
### Getting Started
* Follow the [getting started guide](./docs/getting-started.md) to download and run the project
- ([node](https://nodejs.org/) >= 6,
- **[node-gyp](https://github.com/nodejs/node-gyp#readme)**
- and **[prerequisites](https://github.com/nodejs/node-gyp#installation)**)
+ ([Node.js](https://nodejs.org/) >= 6.5)
* Check the [code recipes](./docs/recipes) used in this boilerplate, or share yours
@@ -217,7 +215,7 @@ requests](CONTRIBUTING.md#pull-requests).
### License
-Copyright © 2014-2016 Kriasoft, LLC. This source code is licensed under the MIT
+Copyright © 2014-present Kriasoft, LLC. This source code is licensed under the MIT
license found in the [LICENSE.txt](https://github.com/kriasoft/react-starter-kit/blob/master/LICENSE.txt)
file. The documentation to the project is licensed under the
[CC BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/) license.
diff --git a/docs/getting-started.md b/docs/getting-started.md
index 13d6215dc8..171db69122 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -4,7 +4,6 @@
* Mac OS X, Windows, or Linux
* [Yarn](https://yarnpkg.com/) package + [Node.js](https://nodejs.org/) v6.5 or newer
- * `node-gyp` prerequisites mentioned [here](https://github.com/nodejs/node-gyp)
* Text editor or IDE pre-configured with React/JSX/Flow/ESlint ([learn more](./how-to-configure-text-editors.md))
### Directory Layout
@@ -33,11 +32,14 @@ Before you start, take a moment to see how the project structure looks like:
│ ├── /clean.js # Cleans up the output (build) folder
│ ├── /copy.js # Copies static files to output (build) folder
│ ├── /deploy.js # Deploys your web application
+│ ├── /postcss.config.js # Configuration for transforming styles with PostCSS plugins
│ ├── /run.js # Helper function for running build automation tasks
│ ├── /runServer.js # Launches (or restarts) Node.js server
│ ├── /start.js # Launches the development web server with "live reload"
│ └── /webpack.config.js # Configurations for client-side and server-side bundles
-└── package.json # The list of 3rd party libraries and utilities
+├── Dockerfile # Commands for building a Docker image for production
+├── package.json # The list of 3rd party libraries and utilities
+└── yarn.lock # Fixed versions of all the dependencies
```
**Note**: The current version of RSK does not contain a Flux implementation.
diff --git a/docs/recipes/how-to-integrate-react-intl.md b/docs/recipes/how-to-integrate-react-intl.md
index 18358b4804..997177dbc9 100644
--- a/docs/recipes/how-to-integrate-react-intl.md
+++ b/docs/recipes/how-to-integrate-react-intl.md
@@ -109,11 +109,11 @@ export default injectIntl(Example);
When running the development server, every source file is watched and parsed for changed messages.
Messages files are updated on the fly.
-If a new definition is found, this definition is added to the end of every used `src/messages/xx-XX.json` file so when commiting, new translations will be at the tail of file.
+If a new definition is found, this definition is added to the end of every used `src/messages/xx-XX.json` file so when committing, new translations will be at the tail of file.
When an untranslated message is removed and its `message` field is empty as well, the message will be deleted from all translation files. This is why the `files` array is present.
-When editiong a translation file, it should be copied to `build/messages/` directory.
+When editing a translation file, it should be copied to `build/messages/` directory.
### Other References
diff --git a/docs/recipes/how-to-use-sass.md b/docs/recipes/how-to-use-sass.md
index edb856da6b..54d0fdabf0 100644
--- a/docs/recipes/how-to-use-sass.md
+++ b/docs/recipes/how-to-use-sass.md
@@ -8,7 +8,9 @@ than `node-sass`.
### Step 1
-Install [`node-sass`](https://github.com/sass/node-sass) and
+Install [`node-sass`](https://github.com/sass/node-sass)
+(includes [node-gyp](https://github.com/nodejs/node-gyp#readme)
+and [prerequisites](https://github.com/nodejs/node-gyp#installation)) and
[`sass-loader`](https://github.com/jtangelder/sass-loader) modules as dev dependencies:
```sh
diff --git a/package.json b/package.json
index 7052abe7fd..f0282b2a9b 100644
--- a/package.json
+++ b/package.json
@@ -6,19 +6,24 @@
"node": ">=6.5",
"npm": ">=3.10"
},
+ "browserslist": [
+ ">1%",
+ "last 4 versions",
+ "Firefox ESR",
+ "not ie < 9"
+ ],
"dependencies": {
"babel-polyfill": "^6.22.0",
- "babel-runtime": "^6.22.0",
"bluebird": "^3.4.7",
"body-parser": "^1.16.0",
"classnames": "^2.2.5",
"cookie-parser": "^1.4.3",
"core-js": "^2.4.1",
"express": "^4.14.1",
- "express-graphql": "^0.6.2",
+ "express-graphql": "^0.6.3",
"express-jwt": "^5.1.0",
"fastclick": "^1.0.6",
- "fbjs": "^0.8.8",
+ "fbjs": "^0.8.9",
"graphql": "^0.9.1",
"history": "^4.5.1",
"isomorphic-style-loader": "^1.1.0",
@@ -45,11 +50,10 @@
"babel-eslint": "^7.1.1",
"babel-loader": "^6.2.10",
"babel-plugin-rewire": "^1.0.0",
- "babel-plugin-transform-runtime": "^6.22.0",
- "babel-preset-latest": "^6.22.0",
+ "babel-preset-env": "^1.1.8",
"babel-preset-react": "^6.22.0",
"babel-preset-react-optimize": "^1.0.1",
- "babel-preset-stage-0": "^6.22.0",
+ "babel-preset-stage-2": "^6.22.0",
"babel-register": "^6.22.0",
"babel-template": "^6.22.0",
"babel-types": "^6.22.0",
@@ -59,17 +63,15 @@
"css-loader": "^0.26.1",
"editorconfig-tools": "^0.1.1",
"enzyme": "^2.7.1",
- "eslint": "^3.14.1",
- "eslint-config-airbnb": "^14.0.0",
+ "eslint": "^3.15.0",
+ "eslint-config-airbnb": "^14.1.0",
"eslint-loader": "^1.6.1",
- "eslint-plugin-css-modules": "^2.1.0",
+ "eslint-plugin-css-modules": "^2.2.0",
"eslint-plugin-import": "^2.2.0",
- "eslint-plugin-jsx-a11y": "^3.0.2",
+ "eslint-plugin-jsx-a11y": "^4.0.0",
"eslint-plugin-react": "^6.9.0",
- "extend": "^3.0.0",
"file-loader": "^0.10.0",
"front-matter": "^2.1.2",
- "git-repository": "^0.1.4",
"glob": "^7.1.1",
"json-loader": "^0.5.4",
"lint-staged": "^3.3.0",
@@ -78,11 +80,11 @@
"mocha": "^3.2.0",
"pixrem": "^3.0.2",
"pleeease-filters": "^3.0.0",
- "postcss": "^5.2.11",
+ "postcss": "^5.2.12",
"postcss-calc": "^5.3.1",
- "postcss-color-function": "^2.0.1",
+ "postcss-color-function": "^3.0.0",
"postcss-custom-media": "^5.0.1",
- "postcss-custom-properties": "^5.0.1",
+ "postcss-custom-properties": "^5.0.2",
"postcss-custom-selectors": "^3.0.0",
"postcss-flexbugs-fixes": "^2.1.0",
"postcss-loader": "^1.2.2",
@@ -103,28 +105,26 @@
"rimraf": "^2.5.4",
"sinon": "^2.0.0-pre.5",
"stylefmt": "^5.1.1",
- "stylelint": "^7.7.1",
- "stylelint-config-standard": "^15.0.1",
+ "stylelint": "^7.8.0",
+ "stylelint-config-standard": "^16.0.0",
"url-loader": "^0.5.7",
"webpack": "^2.2.1",
- "webpack-dev-middleware": "^1.9.0",
+ "webpack-dev-middleware": "^1.10.0",
"webpack-hot-middleware": "^2.16.1",
"write-file-webpack-plugin": "^3.4.2"
},
"babel": {
"presets": [
- "react",
- "stage-0"
- ],
- "plugins": [
- "syntax-trailing-function-commas",
- "transform-async-to-generator",
- "transform-es2015-destructuring",
- "transform-es2015-parameters",
- "transform-es2015-duplicate-keys",
- "transform-es2015-modules-commonjs",
- "transform-exponentiation-operator",
- "transform-runtime"
+ [
+ "env",
+ {
+ "targets": {
+ "node": "current"
+ }
+ }
+ ],
+ "stage-2",
+ "react"
],
"env": {
"test": {
@@ -150,17 +150,10 @@
"browser": true
},
"rules": {
- "arrow-parens": "off",
- "generator-star-spacing": "off",
"import/extensions": "off",
"import/no-extraneous-dependencies": "off",
- "react/forbid-prop-types": "off",
"react/jsx-filename-extension": "off",
- "react/no-array-index-key": "off",
- "react/no-danger": "off",
- "react/no-unused-prop-types": "off",
- "react/prefer-stateless-function": "off",
- "react/require-default-props": "off"
+ "react/prefer-stateless-function": "off"
}
},
"stylelint": {
@@ -187,7 +180,7 @@
},
"pre-commit": "lint:staged",
"lint-staged": {
- "*.{md,sh,txt,xml,html,json}": [
+ "*.{cmd,html,json,md,sh,txt,xml,yml}": [
"editorconfig-tools fix",
"git add"
],
@@ -212,9 +205,10 @@
"copy": "babel-node tools/run copy",
"bundle": "babel-node tools/run bundle",
"build": "babel-node tools/run build",
- "deploy": "babel-node tools/run deployToAzureWebApps",
+ "deploy": "babel-node tools/run deploy",
"render": "babel-node tools/run render",
"serve": "babel-node tools/run runServer",
- "start": "babel-node tools/run start"
+ "start": "babel-node tools/run start",
+ "stats": "babel-node tools/run stats"
}
}
diff --git a/src/client.js b/src/client.js
index b549b101b0..63172448b6 100644
--- a/src/client.js
+++ b/src/client.js
@@ -1,13 +1,12 @@
/**
* React Starter Kit (https://www.reactstarterkit.com/)
*
- * Copyright © 2014-2016 Kriasoft, LLC. All rights reserved.
+ * Copyright © 2014-present Kriasoft, LLC. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE.txt file in the root directory of this source tree.
*/
-import 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import FastClick from 'fastclick';
@@ -16,6 +15,7 @@ import queryString from 'query-string';
import { createPath } from 'history/PathUtils';
import history from './core/history';
import App from './components/App';
+import { updateMeta } from './core/DOMUtils';
import { ErrorReporter, deepForceUpdate } from './core/devUtils';
// Global (context) variables that can be easily accessed from any React component
@@ -30,31 +30,6 @@ const context = {
},
};
-function updateTag(tagName, keyName, keyValue, attrName, attrValue) {
- const node = document.head.querySelector(`${tagName}[${keyName}="${keyValue}"]`);
- if (node && node.getAttribute(attrName) === attrValue) return;
-
- // Remove and create a new tag in order to make it work with bookmarks in Safari
- if (node) {
- node.parentNode.removeChild(node);
- }
- if (typeof attrValue === 'string') {
- const nextNode = document.createElement(tagName);
- nextNode.setAttribute(keyName, keyValue);
- nextNode.setAttribute(attrName, attrValue);
- document.head.appendChild(nextNode);
- }
-}
-function updateMeta(name, content) {
- updateTag('meta', 'name', name, 'content', content);
-}
-function updateCustomMeta(property, content) { // eslint-disable-line no-unused-vars
- updateTag('meta', 'property', property, 'content', content);
-}
-function updateLink(rel, href) { // eslint-disable-line no-unused-vars
- updateTag('link', 'rel', rel, 'href', href);
-}
-
// Switch off the native scroll restoration behavior and handle it manually
// https://developers.google.com/web/updates/2015/09/history-api-scroll-restoration
const scrollPositionsHistory = {};
@@ -114,14 +89,14 @@ let currentLocation = history.location;
let routes = require('./routes').default;
// Re-render the app when window.location changes
-async function onLocationChange(location) {
+async function onLocationChange(location, action) {
// Remember the latest scroll position for the previous location
scrollPositionsHistory[currentLocation.key] = {
scrollX: window.pageXOffset,
scrollY: window.pageYOffset,
};
// Delete stored scroll position for next page if any
- if (history.action === 'PUSH') {
+ if (action === 'PUSH') {
delete scrollPositionsHistory[location.key];
}
currentLocation = location;
@@ -151,23 +126,20 @@ async function onLocationChange(location) {
() => onRenderComplete(route, location),
);
} catch (error) {
- console.error(error); // eslint-disable-line no-console
-
- // Current url has been changed during navigation process, do nothing
- if (currentLocation.key !== location.key) {
- return;
- }
-
// Display the error in full-screen for development mode
if (__DEV__) {
appInstance = null;
document.title = `Error: ${error.message}`;
ReactDOM.render(