Skip to content

Commit ff243c7

Browse files
committed
WIP
1 parent c31d992 commit ff243c7

File tree

16 files changed

+2741
-3594
lines changed

16 files changed

+2741
-3594
lines changed

.eslintrc.js

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,22 @@ module.exports = {
2323
'compat',
2424
],
2525
rules: {
26+
// General
2627
'arrow-parens': ['error', 'as-needed'],
27-
'react/forbid-prop-types': [1, { forbid: ['any']} ],
28+
'function-paren-newline': ["error", "consistent"],
29+
'object-curly-newline': ["error", { consistent: true }],
2830
'no-plusplus': ['error', { allowForLoopAfterthoughts: true }],
31+
'linebreak-style': 0,
32+
'global-require': 0,
33+
'no-restricted-syntax': [2,
34+
...restricted.filter(
35+
r => !['ForOfStatement'].includes(r.selector)
36+
),
37+
],
38+
39+
// React
40+
'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }],
41+
'react/forbid-prop-types': [1, { forbid: ['any']} ],
2942
'react/prefer-stateless-function': [2, { ignorePureComponents: true }],
3043
'react/no-multi-comp': 0,
3144
'react/jsx-closing-bracket-location': [1, 'after-props'],
@@ -37,16 +50,18 @@ module.exports = {
3750
'data',
3851
],
3952
}],
40-
'linebreak-style': 0,
41-
'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }],
42-
'no-restricted-syntax': [2,
43-
...restricted.filter(
44-
r => !['ForOfStatement'].includes(r.selector)
45-
),
46-
],
47-
'global-require': 0,
53+
54+
// Import
4855
'import/no-unresolved': [2, { commonjs: true }],
49-
'compat/compat': 2
56+
57+
// Compat
58+
'compat/compat': 2,
59+
60+
// JSX-a11y
61+
"jsx-a11y/anchor-is-valid": [ "error", {
62+
"components": [ "a" ],
63+
"aspects": [ "noHref", "invalidHref", "preferButton" ]
64+
}],
5065
},
5166
settings: {
5267
'import/resolver': {

CHANGELOG.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,72 @@
1+
UNVERSIONED - 2017-10-17
2+
-----------------------------------------------
3+
4+
## Building
5+
* Fixes static building via `npm run build-static`, by replacing broken `chunk-manifest-webpack-plugin` (closes #55)
6+
7+
## Webpack
8+
* Fixes stats configuration to work with the latest Webpack versions
9+
* Adds CORS config to webpack_dev_server, to enable LAN-wide browser hot-code reloading (closes #99)
10+
11+
## ESLint
12+
* Refactors rules, to be grouped by plugin
13+
* Adds `jsx-a11y/anchor-is-valid` rule to avoid 'href' on React Router `<Link>` attributes
14+
* Adds `function-paren-newline` rule to enforce consistent parenthesis
15+
* Adds `object-curly-newline` rule to allow one-line / multi-line object definitions
16+
* Fixes various kit and src files to conform to new rules
17+
18+
## React
19+
* Bumps to React v16 - officially out of RC!
20+
21+
## Config
22+
* Adds `.disableKoaHelmet()` for disabling [koa-helmet](https://www.npmjs.com/package/koa-helmet) on the server (closes #79)
23+
* Adds `.setKoaHelmetOptions()` for passing options to Koa Helmet
24+
* Sets `.koaHelmetOptions` and `.bodyParserOptions` to null by default
25+
26+
## App
27+
* Disables SSL by default
28+
29+
## General
30+
* Fixes 'local' typo (merges #89 - thanks @kane-c)
31+
* Fixes misspelled `browserslist` file (merges #95 - thanks @klarstrup)
32+
* Adds idiomatic [React Helmet](https://github.com/nfl/react-helmet) `<head>` tags, adds missing html/body attributes, link, style, script and noscript, uses new `Helmet.renderStatic()` call (closes #101 & #94 - thanks @klarstrup)
33+
34+
## NPM
35+
36+
* Bumps packages:
37+
"babel-eslint": "^8.0.1"
38+
"copy-webpack-plugin": "^4.1.1",
39+
"cross-env": "^5.1.0",
40+
"eslint": "^4.9.0",
41+
"eslint-config-airbnb": "^16.1.0",
42+
"eslint-plugin-compat": "^2.0.1",
43+
"eslint-plugin-jsx-a11y": "^6.0.2",
44+
"eslint-plugin-react": "^7.4.0",
45+
"extract-text-webpack-plugin": "^3.0.1",
46+
"file-loader": "^1.1.5",
47+
"graphql-tag": "^2.5.0",
48+
"iltorb": "^2.0.1"
49+
"jest": "^21.2.1",
50+
"less": "^3.0.0-alpha.3",
51+
"postcss-loader": "^2.0.8",
52+
"resolve-url-loader": "^2.1.1",
53+
"rimraf": "^2.6.2",
54+
"serve": "^6.2.0",
55+
"style-loader": "^0.19.0",
56+
"webpack": "^3.8.0",
57+
"webpack-chunk-hash": "^0.5.0",
58+
"webpack-config": "^7.5.0",
59+
"webpack-dev-server": "^2.9.2",
60+
"webpack-manifest-plugin": "^1.3.2",
61+
"apollo-server-koa": "^1.1.7",
62+
"graphql": "^0.11.7",
63+
"koa-send": "^4.1.1",
64+
"prop-types": "^15.6.0",
65+
"react": "^16.0.0",
66+
"react-apollo": "^1.4.16",
67+
"react-dom": "^16.0.0",
68+
"react-hot-loader": "^3.1.1"
69+
170
2.8.5 - 2017-09-07
271
-----------------------------------------------
372

File renamed without changes.

kit/config.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ if (SERVER) {
9292
// Flag for setting whether plain HTTP should be disabled
9393
this.enableHTTP = true;
9494

95+
// Flag for enabling Koa Helmet HTTP hardening. True, by default.
96+
this.enableKoaHelmet = true;
97+
this.koaHelmetOptions = null;
98+
9599
// Force SSL. Rewrites all non-SSL queries to SSL. False, by default.
96100
this.enableForceSSL = false;
97101

@@ -110,9 +114,9 @@ if (SERVER) {
110114
// default to the string value
111115
this.graphiQL = false;
112116

113-
// Enable body parsing by default. Leave `koa-bodyparser` opts as default
117+
// Enable body parsing by default.
114118
this.enableBodyParser = true;
115-
this.bodyParserOptions = {};
119+
this.bodyParserOptions = null;
116120

117121
// CORS options for `koa-cors`
118122
this.corsOptions = {};
@@ -159,6 +163,15 @@ if (SERVER) {
159163
this.bodyParserOptions = opt;
160164
}
161165

166+
// Disable Koa Helmet option, to prevent HTTP hardening by default
167+
disableKoaHelmet() {
168+
this.enableKoaHelmet = false;
169+
}
170+
171+
setKoaHelmetOptions(opt = {}) {
172+
this.koaHelmetOptions = opt;
173+
}
174+
162175
// 404 handler for the server. By default, `kit/entry/server.js` will
163176
// simply return a 404 status code without modifying the HTML render. By
164177
// setting a handler here, this will be returned instead

kit/entry/browser.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ const Root = (() => {
8080
if (module.hot) {
8181
// <AppContainer> will respond to our Hot Module Reload (HMR) changes
8282
// back from WebPack, and handle re-rendering the chain as needed
83-
const AppContainer = require('react-hot-loader').AppContainer;
83+
const { AppContainer } = require('react-hot-loader');
8484

8585
// Start our 'listener' at the root component, so that any changes that
8686
// occur in the hierarchy can be captured

kit/entry/server.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ export function createReactHandler(css = [], scripts = [], chunkManifest = {}) {
213213
// store state so that the browser can continue from the server
214214
const reactStream = ReactDOMServer.renderToNodeStream(
215215
<Html
216-
head={Helmet.rewind()}
216+
helmet={Helmet.renderStatic()}
217217
window={{
218218
webpackManifest: chunkManifest,
219219
__STATE__: ctx.store.getState(),
@@ -254,9 +254,6 @@ const app = new Koa()
254254
// Adds CORS config
255255
.use(koaCors(config.corsOptions))
256256

257-
// Preliminary security for HTTP headers
258-
.use(koaHelmet())
259-
260257
// Error wrapper. If an error manages to slip through the middleware
261258
// chain, it will be caught and logged back here
262259
.use(async (ctx, next) => {
@@ -311,6 +308,11 @@ if (config.enableForceSSL) {
311308
app.use(koaSSL(config.enableForceSSL));
312309
}
313310

311+
// Middleware to add preliminary security for HTTP headers via Koa Helmet
312+
if (config.enableKoaHelmet) {
313+
app.use(koaHelmet(config.koaHelmetOptions));
314+
}
315+
314316
// Attach custom middleware
315317
config.middleware.forEach(middlewareFunc => app.use(middlewareFunc));
316318

kit/entry/server_prod.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,8 @@ import server, { createReactHandler, staticMiddleware } from './server';
2727
// ----------------------
2828

2929
// Read in manifest files
30-
const [manifest, chunkManifest] = ['manifest', 'chunk-manifest'].map(
31-
name => JSON.parse(
32-
readFileSync(path.resolve(PATHS.dist, `${name}.json`), 'utf8'),
33-
),
34-
);
30+
const [manifest, chunkManifest] = ['manifest', 'chunk-manifest']
31+
.map(name => JSON.parse(readFileSync(path.resolve(PATHS.dist, `${name}.json`), 'utf8')));
3532

3633
// Get manifest values
3734
const css = manifest['browser.css'];

kit/lib/redux.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ function unwind(reducer = true) {
3535
//
3636
// If we're not looking for reducers, it'll pull out the `initialState`
3737
// variable instead, which we'll further process below
38-
const r = Object.assign({},
39-
...[].concat([...config.reducers].map(arr => ({
38+
const r = Object.assign(
39+
{}, ...[].concat([...config.reducers].map(arr => ({
4040
[arr[0]]: reducer ? function defaultReducer(state, action) {
4141
// If `state` === undefined, this is Redux sending a sentinel value
4242
// to check our set-up. So we'll send back a plain object to prove

kit/lib/routing.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,13 @@ export class Redirect extends React.PureComponent {
7979
}
8080

8181
render() {
82-
const { to, from, push, permanent } = this.props;
82+
const {
83+
to,
84+
from,
85+
push,
86+
permanent,
87+
} = this.props;
88+
8389
const code = permanent ? 301 : 302;
8490
return (
8591
<Status code={code}>

kit/views/ssr.js

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,37 @@ import PropTypes from 'prop-types';
99

1010
// ----------------------
1111

12-
const Html = ({ head, scripts, window, css, children }) => (
13-
<html lang="en" prefix="og: http://ogp.me/ns#">
12+
const Html = ({ helmet, scripts, window, css, children }) => (
13+
<html lang="en" prefix="og: http://ogp.me/ns#" {...helmet.htmlAttributes.toString()}>
1414
<head>
15+
{helmet.title.toComponent()}
1516
<meta charSet="utf-8" />
1617
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
1718
<meta httpEquiv="Content-Language" content="en" />
1819
<meta name="viewport" content="width=device-width, initial-scale=1" />
19-
{head.meta.toComponent()}
20+
{helmet.meta.toComponent()}
2021
<link rel="stylesheet" href={css} />
21-
{head.title.toComponent()}
22+
{helmet.link.toComponent()}
23+
{helmet.style.toComponent()}
24+
{helmet.script.toComponent()}
25+
{helmet.noscript.toComponent()}
2226
</head>
23-
<body>
27+
<body {...helmet.bodyAttributes.toComponent()}>
2428
<div id="main">{children}</div>
2529
<script
2630
dangerouslySetInnerHTML={{
2731
__html: Object.keys(window).reduce(
2832
(out, key) => out += `window.${key}=${JSON.stringify(window[key])};`,
29-
''),
33+
'',
34+
),
3035
}} />
3136
{scripts.map(src => <script key={src} src={src} />)}
3237
</body>
3338
</html>
3439
);
3540

3641
Html.propTypes = {
37-
head: PropTypes.object.isRequired,
42+
helmet: PropTypes.object.isRequired,
3843
window: PropTypes.object.isRequired,
3944
scripts: PropTypes.arrayOf(PropTypes.string).isRequired,
4045
css: PropTypes.string.isRequired,

0 commit comments

Comments
 (0)