jekyll-theme-alta-docs 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,600 @@
1
+ {% assign project_name = 'project-name' %}
2
+ {% if include.project_name %}
3
+ {% assign project_name = include.project_name %}
4
+ {% endif %}
5
+
6
+ *Node: 10.16.0, Yarn: 1.21.1, NPM: 6.9.0, NPX: 6.9.0*
7
+
8
+ **Purpose:** Create-react-app (Client Side Rendering)
9
+
10
+ ### Prerequisites
11
+
12
+ * Node installed
13
+ * Yarn, NPM or NPX installed
14
+
15
+ ### A) Create project with Create-react-app
16
+
17
+ 1. Run:
18
+
19
+ $ npx create-react-app {{ project_name }}-web
20
+
21
+ # ...OR...
22
+ $ yarn create react-app {{ project_name }}-web
23
+
24
+ # ...OR
25
+ $ npm init react-app {{ project_name }}-web
26
+
27
+ 2. Go to the project folder:
28
+
29
+ $ cd {{ project_name }}-web
30
+
31
+
32
+
33
+ ### B) Setup project tree
34
+
35
+ The example of the project tree. The final outcome depends on the project needs.
36
+
37
+ {% include guidelines/react/react_project_tree.md %}
38
+
39
+
40
+
41
+ #### 1. Config
42
+
43
+ Create folder `src/config` and add `src/config/app.js` file:
44
+
45
+ ```javascript
46
+ const prod = {
47
+ API_URL: 'https://domain.com/api/v1/'
48
+ }
49
+
50
+ const dev = {
51
+ API_URL: 'http://xxx.xxx.xx.xx:4000/api/v1/'
52
+ }
53
+
54
+ const config = process.env.NODE_ENV === 'production'
55
+ ? prod
56
+ : dev
57
+
58
+ // const EXAMPLE_VAR = 'xxx'
59
+
60
+ export default {
61
+ ...config,
62
+ // EXAMPLE_VAR,
63
+ }
64
+ ```
65
+
66
+ #### 2. Add basic folders to the project tree
67
+
68
+ ```
69
+ |--src
70
+ |-- assets
71
+ | |-- images
72
+ | |-- .keep
73
+ |
74
+ |-- components
75
+ | |-- UI
76
+ | |-- .keep
77
+ |
78
+ |-- containers
79
+ | |-- .keep
80
+ |
81
+ |-- helpers
82
+ | |-- .keep
83
+ |
84
+ |-- layouts
85
+ | |-- .keep
86
+ |
87
+ |-- models
88
+ | |-- .keep
89
+ |
90
+ |-- modules
91
+ | |-- .keep
92
+ |
93
+ |-- services
94
+ |-- .keep
95
+ ```
96
+
97
+
98
+
99
+ #### 3. Add Routes and set up App.jsx
100
+
101
+ Install:
102
+
103
+ ```bash
104
+ $ yarn add react-router-dom
105
+ ```
106
+
107
+ Create `src/routes` folder and add `src/routes/routes.jsx` file:
108
+
109
+ ```javascript
110
+ import React from 'react'
111
+ import {
112
+ Route,
113
+ Switch
114
+ } from 'react-router'
115
+ import HomeRoute from './home/HomeRoute'
116
+
117
+ const routes = (
118
+ <Switch>
119
+ <Route exact path='/' component={HomeRoute} />
120
+ </Switch>
121
+ )
122
+
123
+ export default routes
124
+ ```
125
+
126
+ Add file `src/routes/home/HomeRoute.jsx`:
127
+
128
+ ```javascript
129
+ import React from 'react'
130
+
131
+ const Home = () => (
132
+ <div>
133
+ <h1>Home page</h1>
134
+ </div>
135
+ )
136
+
137
+ export default Home
138
+ ```
139
+
140
+ Add `src/history.js`:
141
+
142
+ ```javascript
143
+ import { createBrowserHistory } from 'history'
144
+
145
+ export default createBrowserHistory()
146
+ ```
147
+
148
+
149
+ Edit `src/App.jsx`:
150
+
151
+ ```javascript
152
+ import React, {
153
+ useState,
154
+ useEffect,
155
+ } from 'react'
156
+ import PropTypes from 'prop-types'
157
+ import { Router } from 'react-router'
158
+ import routes from './routes/routes'
159
+ import history from './history'
160
+ import './App.css'
161
+
162
+ function App() {
163
+ return (
164
+ <div className='app'>
165
+ <Router history={history}>
166
+ {routes}
167
+ </Router>
168
+ </div>
169
+ )
170
+ }
171
+
172
+ export default App
173
+ ```
174
+
175
+
176
+
177
+
178
+
179
+ #### 4. Add initialization script
180
+
181
+ Add file `src/Init.js`:
182
+
183
+ ```javascript
184
+ /**
185
+ * Initialization script loading functions in a sequence.
186
+ *
187
+ * Statuses:
188
+ * 0 - sequence has been halted. It may mean that there was an error during initialization
189
+ * 1 - initialized with success.
190
+ * 2 - redirection
191
+ *
192
+ * @returns {{status: number, message: string, data: Object }}
193
+ */
194
+ class Init {
195
+ static init() {
196
+ return this.firstFunction()
197
+ }
198
+
199
+ static async firstFunction() {
200
+ if (true) {
201
+ return this.secondFunction()
202
+ }
203
+ return {
204
+ status: 0,
205
+ message: 'APP_INITIALIZATION_FAILED',
206
+ }
207
+ }
208
+
209
+ static async secondFunction() {
210
+ return {
211
+ status: 0,
212
+ message: 'SUCCESS',
213
+ data: { a: 1, b: 2 }
214
+ }
215
+ }
216
+ }
217
+
218
+ export default Init
219
+ ```
220
+
221
+ Add the Init to the `src/App.jsx`:
222
+
223
+ ```javascript
224
+ import Init from './Init.js'
225
+
226
+ function App() {
227
+ const [initPerformed, setInitPerformed] = useState(false)
228
+ useEffect(() => {
229
+ if (!initPerformed) {
230
+ initializeApp()
231
+ }
232
+ }, [initPerformed])
233
+
234
+ async function initializeApp() {
235
+ await Init.init()
236
+ // OR:
237
+ // const response = await Init.init()
238
+ // Do something with response.. (i.e. Set Redux)
239
+ setInitPerformed(true)
240
+ }
241
+
242
+ (...)
243
+ }
244
+ ```
245
+
246
+
247
+ #### 5. Add I18n
248
+
249
+ Install:
250
+
251
+ ```bash
252
+ $ yarn add react-i18next i18next
253
+ ```
254
+
255
+ Create file `src/i18n.js`:
256
+
257
+ ```javascript
258
+ import i18n from "i18next"
259
+ import { initReactI18next } from "react-i18next"
260
+
261
+ const appEn = require('./locales/en/app.json')
262
+
263
+ const resources = {
264
+ en: {
265
+ app: appEn
266
+ }
267
+ }
268
+
269
+ i18n
270
+ .use(initReactI18next) // passes i18n down to react-i18next
271
+ .init({
272
+ resources,
273
+ lng: 'en',
274
+ fallbackLng: 'en',
275
+ interpolation: {
276
+ escapeValue: false // react already safes from xss
277
+ }
278
+ })
279
+
280
+ export default i18n
281
+ ```
282
+
283
+ Add file: `src/locales/en/app.json`
284
+
285
+ ```json
286
+ {
287
+ "MY_TRANSLATION": "Translation example"
288
+ }
289
+ ```
290
+
291
+ Import `i18n` in `src/index.js`:
292
+
293
+ ```javascript
294
+ import './i18n'
295
+ ```
296
+
297
+
298
+ #### 6. Add Redux
299
+
300
+ **Add Redux only if necessary.**
301
+
302
+ Install:
303
+
304
+ ```bash
305
+ $ yarn add redux react-redux redux-devtools-extension redux-thunk
306
+ ```
307
+
308
+ Add folders:
309
+
310
+ ```
311
+ |-- src
312
+ |-- actions
313
+ | |-- .keep
314
+ |
315
+ |-- reducers
316
+ | |-- index.js
317
+ |
318
+ |-- store.js
319
+ ```
320
+
321
+ Edit `src/reducers/index.js`:
322
+
323
+ ```javascript
324
+ import { combineReducers } from 'redux'
325
+ // import appReducer from './appReducer'
326
+
327
+ export default () => combineReducers({
328
+ // app: appReducer,
329
+ })
330
+ ```
331
+
332
+ Edit `src/store.js`:
333
+
334
+ ```javascript
335
+ import { createStore, applyMiddleware } from 'redux'
336
+ import thunk from 'redux-thunk'
337
+ import { composeWithDevTools } from 'redux-devtools-extension/developmentOnly'
338
+ import rootReducer from './reducers'
339
+
340
+
341
+ export const store = createStore(
342
+ rootReducer(),
343
+ composeWithDevTools(
344
+ applyMiddleware(
345
+ thunk
346
+ )
347
+ )
348
+ )
349
+ export default store
350
+ ```
351
+
352
+ Edit `src/index.js`:
353
+
354
+ ```javascript
355
+ (...)
356
+ import { Provider } from 'react-redux'
357
+ import { store } from './store'
358
+ (...)
359
+
360
+ ReactDOM.render(
361
+ <React.StrictMode>
362
+ <Provider store={store}>
363
+ <App />
364
+ </Provider>
365
+ </React.StrictMode>,
366
+ document.getElementById('root')
367
+ )
368
+ (...)
369
+
370
+ ```
371
+
372
+
373
+ ### C) Install other Node modules
374
+
375
+ Install only required modules.
376
+
377
+ #### 1. Axios
378
+
379
+ ```bash
380
+ $ yarn add axios
381
+ ```
382
+
383
+ #### 2. AWS Amplify
384
+
385
+ ```bash
386
+ $ yarn add aws-amplify
387
+ ```
388
+
389
+
390
+
391
+
392
+ ### D) Set up SCSS and 7-1 pattern
393
+
394
+ Install:
395
+
396
+ ```bash
397
+ $ yarn add node-sass
398
+ ```
399
+
400
+ Rename `src/App.css` to `src/App.scss` and change import in `src/App.js`:
401
+
402
+ ```javascript
403
+ import './App.scss'
404
+ ```
405
+
406
+ Create `src/styles` folder and recreate 7-1 pattern:
407
+
408
+ ```
409
+ |
410
+ |– base/
411
+ | |– _reset.scss # Reset/normalize
412
+ | |– _typography.scss # Typography rules
413
+ | ... # Etc…
414
+ |
415
+ |– components/
416
+ | |– .keep
417
+ |
418
+ |– layout/
419
+ | |– .keep
420
+ |
421
+ |– pages/
422
+ | |– .keep
423
+ |
424
+ |– themes/
425
+ | |– _theme.scss # Default theme
426
+ |
427
+ |– utils/
428
+ | |– _variables.scss # Sass Variables
429
+ | |– _functions.scss # Sass Functions
430
+ | |– _mixins.scss # Sass Mixins
431
+ | |– _helpers.scss # Class & placeholders helpers
432
+ |
433
+ |– vendors/
434
+ | |– .keep
435
+ |
436
+ |
437
+ |– main.scss # Main Sass file
438
+ ```
439
+
440
+ Edit `src/styles/main.scss`:
441
+
442
+ ```scss
443
+ @import
444
+ 'utils/variables',
445
+ 'utils/functions',
446
+ 'utils/mixins',
447
+ 'utils/helpers';
448
+
449
+ // @import 'vendors/bootstrap';
450
+
451
+ @import
452
+ 'base/reset',
453
+ 'base/typography';
454
+
455
+ // @import
456
+ // 'layout/navigation',
457
+ // 'layout/grid',
458
+ // 'layout/header',
459
+ // 'layout/footer',
460
+ // 'layout/sidebar',
461
+ // 'layout/forms';
462
+
463
+ // @import 'components/buttons';
464
+
465
+ // @import 'pages/home';
466
+
467
+ @import 'themes/theme';
468
+
469
+ ```
470
+
471
+
472
+ Import `src/styles/main.scss` in `src/App.scss`:
473
+
474
+ ```scss
475
+ @import './styles/main.scss'
476
+ ```
477
+
478
+ ### E) Set up ESlint and Prettier
479
+
480
+ Install:
481
+
482
+ ```bash
483
+ $ yarn add -D babel-eslint eslint eslint-config-airbnb \
484
+ eslint-config-prettier eslint-plugin-react eslint-plugin-import \
485
+ prettier pretty-quick eslint-plugin-jsx-a11y
486
+ ```
487
+
488
+ Initialize eslint:
489
+
490
+ ```bash
491
+ $ ./node_modules/bin/eslint.js --init
492
+ # OR:
493
+ $ npx eslint --init
494
+ ```
495
+
496
+ Add file `.prettierrc`:
497
+
498
+ ```javascript
499
+ {
500
+ "printWidth": 100,
501
+ "trailingComma": "all",
502
+ "tabWidth": 2,
503
+ "semi": false,
504
+ "singleQuote": true
505
+ }
506
+ ```
507
+
508
+ Add file `.eslintignore`:
509
+
510
+ ```
511
+ build/*
512
+ node_modules/*
513
+ ```
514
+
515
+ Add file `.eslintrc.js`:
516
+
517
+ ```
518
+ module.exports = {
519
+ "extends": ["airbnb", "prettier"],
520
+ "parser": "babel-eslint",
521
+ "env": {
522
+ "browser": true,
523
+ "es2021": true
524
+ },
525
+ "parserOptions": {
526
+ "ecmaFeatures": {
527
+ "jsx": true
528
+ },
529
+ "ecmaVersion": 12,
530
+ "sourceType": "module"
531
+ },
532
+ "plugins": [
533
+ "react"
534
+ ],
535
+ "rules": {
536
+ "semi": [2, "never"],
537
+ "no-use-before-define": ["error", { "functions": false, "classes": false, "variables": false }],
538
+ "import/no-extraneous-dependencies": ["error", {"devDependencies": false, "optionalDependencies": false, "peerDependencies": false}],
539
+ "import/no-cycle": 0,
540
+ 'jsx-quotes': ["error", "prefer-single"],
541
+ "no-underscore-dangle": 0,
542
+ "react/require-default-props": 0,
543
+ "jsx-a11y/anchor-is-valid": 0,
544
+ "jsx-a11y/label-has-for": [ 2, {
545
+ "required": {
546
+ "some": [ "nesting", "id" ]
547
+ }
548
+ }],
549
+ "react-hooks/exhaustive-deps": 0,
550
+ "react/forbid-prop-types": 0,
551
+ "comma-dangle": ["error", {
552
+ "arrays": "only-multiline",
553
+ "objects": "only-multiline",
554
+ "imports": "only-multiline",
555
+ "exports": "only-multiline",
556
+ "functions": "never",
557
+ }],
558
+ "react/jsx-pascal-case": 0,
559
+ "react/no-array-index-key": 0,
560
+ },
561
+ };
562
+
563
+ ```
564
+
565
+ Add to `package.json`:
566
+
567
+ ```json
568
+ "scripts": {
569
+ (...)
570
+ "lint": "./node_modules/eslint/bin/eslint.js --ext .js --ext .jsx .",
571
+ "format": "prettier --write \"**/*.+(js|jsx|json|css|md)\""
572
+ },
573
+ ```
574
+
575
+ And you can run:
576
+
577
+ ```bash
578
+ $ yarn lint
579
+ $ yarn format
580
+ ```
581
+
582
+
583
+
584
+ ### F) Set up tests
585
+
586
+ TODO
587
+
588
+
589
+
590
+ ### G) Edit README.md
591
+
592
+ ```markdown
593
+ {% include templates/react/react_readme.md project_name=project_name %}
594
+ ```
595
+
596
+
597
+
598
+ ### H) Service worker
599
+
600
+ TODO