Skip to content

Commit 7e9ddc0

Browse files
author
Nelsie
committed
Added linter
1 parent 4b82507 commit 7e9ddc0

File tree

12 files changed

+148
-43
lines changed

12 files changed

+148
-43
lines changed

README.md

+46
Original file line numberDiff line numberDiff line change
@@ -275,16 +275,62 @@ $ git clone [email protected]:heroku/devcenter-embedded-tomcat.git
275275
```
276276

277277

278+
278279
## Adding Client files
279280
If you have experience using `ReactJS`, `Redux`, `React Router` and `Webpack` then by going through the folder/files will give you the idea on how to accomplish this
280281

281282

283+
284+
## Adding a Linter: [ESLint](https://eslint.org/)
285+
### Local installation
286+
```
287+
$ npm i eslint --save-dev
288+
```
289+
290+
### Configuration file setup
291+
```
292+
$ ./node_modules/.bin/eslint --init
293+
```
294+
295+
### ESLint prerequisites
296+
* [babel-eslint](https://github.com/babel/babel-eslint) - Lint all valid Babel code
297+
* [eslint-loader](https://github.com/MoOx/eslint-loader) - Linting JS files using eslint with webpack
298+
* [eslint-plugin-react](https://github.com/yannickcr/eslint-plugin-react) - React specific linting rules for ESLint
299+
300+
### Additional rules to get rid of React warnings
301+
```
302+
rules: {
303+
...
304+
"react/jsx-uses-react": [2],
305+
"react/jsx-uses-vars": [2],
306+
...
307+
}
308+
```
309+
310+
### Additional environment to get rid of other warnings
311+
```
312+
env: {
313+
...
314+
// Webpack module.hot
315+
"commonjs": true,
316+
// require()
317+
"amd": true
318+
...
319+
}
320+
```
321+
322+
323+
282324
## References
283325
[For Java Web installation](https://devcenter.heroku.com/articles/create-a-java-web-application-using-embedded-tomcat)
284326

285327
[For react/redux/react-router-dom integration](https://medium.com/@notrab/getting-started-with-create-react-app-redux-react-router-redux-thunk-d6a19259f71f)
286328

287329
[For Webpack integration](https://medium.com/@rajaraodv/webpacks-hmr-react-hot-loader-the-missing-manual-232336dc0d96)
288330

331+
[For configuring `eslint-loader` with Webpack](https://www.learnhowtoprogram.com/react/react-fundamentals/building-an-environment-automatic-linting-with-webpack)
332+
333+
334+
289335
## Dev Tools
290336
[Redux DevTools](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=en)

src/main/webapp/client/.eslintrc.json

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"env": {
3+
// Defines require() and define() as global variables as per the amd spec
4+
"amd": true,
5+
// window,document
6+
"browser": true,
7+
// Webpack module.hot
8+
"commonjs": true,
9+
"es6": true,
10+
// Node process.env
11+
"node": true
12+
},
13+
"extends": "eslint:recommended",
14+
// Lint all valid Babel code
15+
"parser": "babel-eslint",
16+
"parserOptions": {
17+
"ecmaFeatures": {
18+
"experimentalObjectRestSpread": true,
19+
"jsx": true
20+
},
21+
"sourceType": "module"
22+
},
23+
"plugins": ["react"],
24+
"rules": {
25+
"indent": ["error", 2],
26+
"linebreak-style": ["error", "unix"],
27+
"quotes": ["error", "double"],
28+
// Get rid of React warnings
29+
"react/jsx-uses-react": [2],
30+
"react/jsx-uses-vars": [2],
31+
"semi": ["error", "always"]
32+
}
33+
}

src/main/webapp/client/app/components/App.js

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import React from "react";
2-
import { Route, Link } from "react-router-dom";
32

43
import Aux from "./Aux";
54
import Header from "./header";

src/main/webapp/client/app/components/Routes.js

-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,3 @@ export default () => (
99
<Route exact path="/about" component={About} />
1010
</Switch>
1111
);
12-
// render={() => System.import("./home").then(module => module.default)}

src/main/webapp/client/app/components/header/index.js

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import React from "react";
2-
import { Link } from "react-router-dom";
32
import Nav from "../nav";
43

54
import "./style.scss";

src/main/webapp/client/app/components/home/style.scss

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
&__note {
55
color: $secondary-grey-color;
66
font-size: 13px;
7-
margin: 0 0 8px 20px;
7+
margin: 0 0 8px 16px;
88

99
&:before {
10-
content: "//";
10+
content: "#";
1111
float: left;
12-
margin-left: -20px;
12+
margin-left: -16px;
1313
}
1414
}
1515
&__footer {

src/main/webapp/client/app/components/material-button/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from "react";
22

33
import MaterialRipple from "../material-ripple";
4+
45
import "./style.scss";
56

67
const MaterialButton = props => (

src/main/webapp/client/app/components/nav/index.js

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import React from "react";
2-
import { Link } from "react-router-dom";
32

43
import MaterialRipple from "../material-ripple";
54

src/main/webapp/client/app/reducers/counter.js

+24-24
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,33 @@ import * as types from "../actions";
22

33
export default (state = {}, action) => {
44
switch (action.type) {
5-
case types.INCREMENT_REQUESTED:
6-
return {
7-
...state,
8-
isIncrementing: true
9-
};
5+
case types.INCREMENT_REQUESTED:
6+
return {
7+
...state,
8+
isIncrementing: true
9+
};
1010

11-
case types.INCREMENT:
12-
return {
13-
...state,
14-
count: state.count + 5,
15-
isIncrementing: !state.isIncrementing
16-
};
11+
case types.INCREMENT:
12+
return {
13+
...state,
14+
count: state.count + 5,
15+
isIncrementing: !state.isIncrementing
16+
};
1717

18-
case types.DECREMENT_REQUESTED:
19-
return {
20-
...state,
21-
isDecrementing: true
22-
};
18+
case types.DECREMENT_REQUESTED:
19+
return {
20+
...state,
21+
isDecrementing: true
22+
};
2323

24-
case types.DECREMENT:
25-
return {
26-
...state,
27-
count: state.count - 5,
28-
isDecrementing: !state.isDecrementing
29-
};
24+
case types.DECREMENT:
25+
return {
26+
...state,
27+
count: state.count - 5,
28+
isDecrementing: !state.isDecrementing
29+
};
3030

31-
default:
32-
return state;
31+
default:
32+
return state;
3333
}
3434
};

src/main/webapp/client/app/store/index.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@ import rootReducer from "../reducers";
66

77
export const history = createHistory();
88

9+
// To get rid of eslint warning
10+
/*global __INITIAL_STATE__*/
911
const initialState = __INITIAL_STATE__ || {};
1012
const enhancers = [];
1113
const middleware = [thunk, routerMiddleware(history)];
1214

13-
// if (process.env.NODE_ENV === "development") {
14-
if (typeof window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ === "function") {
15-
enhancers.push(window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__());
15+
if (process.env.APP_ENV === "development") {
16+
if (typeof window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ === "function") {
17+
enhancers.push(window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__());
18+
}
1619
}
17-
// }
1820

1921
const composedEnhancers = compose(applyMiddleware(...middleware), ...enhancers);
2022

src/main/webapp/client/package.json

+4
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,16 @@
2222
},
2323
"devDependencies": {
2424
"babel-core": "^6.26.0",
25+
"babel-eslint": "^8.0.2",
2526
"babel-loader": "^7.1.2",
2627
"babel-preset-es2015": "^6.24.1",
2728
"babel-preset-react": "^6.24.1",
2829
"babel-preset-stage-2": "^6.24.1",
2930
"clean-webpack-plugin": "^0.1.17",
3031
"css-loader": "^0.28.7",
32+
"eslint": "^4.10.0",
33+
"eslint-loader": "^1.9.0",
34+
"eslint-plugin-react": "^7.4.0",
3135
"node-sass": "^4.5.3",
3236
"postcss-loader": "^2.0.8",
3337
"sass-loader": "^6.0.6",

src/main/webapp/client/webpack.dev.config.js

+31-8
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ const path = require("path");
22
const webpack = require("webpack");
33
const CleanWebpackPlugin = require("clean-webpack-plugin");
44

5-
const BUILD_DIR = path.resolve(__dirname, "../public");
65
const APP_DIR = path.resolve(__dirname, "./app");
76
const SCSS_RESOURCES = path.resolve(__dirname, "./app/scss/resources/*.scss");
87

@@ -31,10 +30,7 @@ module.exports = {
3130
// Will output bundle.js
3231
filename: "bundle.js",
3332

34-
// Path of output files
35-
path: BUILD_DIR,
36-
37-
// Required for webpack-dev-server
33+
// Required by webpack-dev-server for outputting bundle
3834
publicPath: "/public/"
3935
},
4036

@@ -68,11 +64,28 @@ module.exports = {
6864
new webpack.NamedModulesPlugin(),
6965

7066
// Enable HMR globally; Generate hot update chunks
71-
new webpack.HotModuleReplacementPlugin()
67+
new webpack.HotModuleReplacementPlugin(),
68+
69+
new webpack.DefinePlugin({
70+
"process.env.APP_ENV": JSON.stringify("development")
71+
})
7272
],
7373

7474
module: {
75-
loaders: [
75+
rules: [
76+
// Tell Webpack to detect errors/warnings but should still be able to build (but with warnings)
77+
{
78+
enforce: "pre", // specify as pre-loader; lint files not modified by other loaders (like babel-loader)
79+
test: /\.js$/,
80+
include: APP_DIR,
81+
loader: "eslint-loader",
82+
options: {
83+
emitWarning: true, // instruct eslint-loader to output errors/warning in the console
84+
configFile: "./.eslintrc.json" // points loader to ESLint config file
85+
}
86+
},
87+
88+
// Transpiling JS files using babel and webpack
7689
{
7790
test: /\.js$/,
7891
include: APP_DIR,
@@ -82,6 +95,7 @@ module.exports = {
8295
presets: ["es2015", "react", "stage-2"]
8396
}
8497
},
98+
8599
{
86100
test: /\.scss$/,
87101
include: APP_DIR,
@@ -98,7 +112,16 @@ module.exports = {
98112
},
99113

100114
// For auto prefixing
101-
"postcss-loader",
115+
// After installing ESLint, needed to add config here,
116+
// thus config file (.postcssrc) is no longer in used
117+
{
118+
loader: "postcss-loader",
119+
options: {
120+
plugins: () => [
121+
/* PostCSS Plugins */
122+
]
123+
}
124+
},
102125

103126
// Compiles sass to css
104127
"sass-loader",

0 commit comments

Comments
 (0)