├── assets
├── linter.png
├── set_up_five.png
├── set_up_four.png
├── set_up_nine.png
├── set_up_one.png
├── set_up_six.png
├── set_up_ten.png
├── set_up_two.png
├── linter_forced.png
├── set_up_eight.png
├── set_up_seven.png
└── set_up_three.png
├── src
├── images
│ └── helloworld.gif
├── fonts
│ └── prototype.regular.ttf
├── index.scss
└── index.jsx
├── .babelrc
├── .eslintrc.js
├── public
└── index.html
├── webpack.config.js
├── package.json
├── bonus
├── image_assets_configuration.md
├── custom_font_configuration.md
├── sass_configuration.md
└── eslint_configuration.md
├── .gitignore
└── README.md
/assets/linter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySylvia/HowTo-React-Webpack-Babel/HEAD/assets/linter.png
--------------------------------------------------------------------------------
/assets/set_up_five.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySylvia/HowTo-React-Webpack-Babel/HEAD/assets/set_up_five.png
--------------------------------------------------------------------------------
/assets/set_up_four.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySylvia/HowTo-React-Webpack-Babel/HEAD/assets/set_up_four.png
--------------------------------------------------------------------------------
/assets/set_up_nine.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySylvia/HowTo-React-Webpack-Babel/HEAD/assets/set_up_nine.png
--------------------------------------------------------------------------------
/assets/set_up_one.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySylvia/HowTo-React-Webpack-Babel/HEAD/assets/set_up_one.png
--------------------------------------------------------------------------------
/assets/set_up_six.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySylvia/HowTo-React-Webpack-Babel/HEAD/assets/set_up_six.png
--------------------------------------------------------------------------------
/assets/set_up_ten.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySylvia/HowTo-React-Webpack-Babel/HEAD/assets/set_up_ten.png
--------------------------------------------------------------------------------
/assets/set_up_two.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySylvia/HowTo-React-Webpack-Babel/HEAD/assets/set_up_two.png
--------------------------------------------------------------------------------
/assets/linter_forced.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySylvia/HowTo-React-Webpack-Babel/HEAD/assets/linter_forced.png
--------------------------------------------------------------------------------
/assets/set_up_eight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySylvia/HowTo-React-Webpack-Babel/HEAD/assets/set_up_eight.png
--------------------------------------------------------------------------------
/assets/set_up_seven.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySylvia/HowTo-React-Webpack-Babel/HEAD/assets/set_up_seven.png
--------------------------------------------------------------------------------
/assets/set_up_three.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySylvia/HowTo-React-Webpack-Babel/HEAD/assets/set_up_three.png
--------------------------------------------------------------------------------
/src/images/helloworld.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySylvia/HowTo-React-Webpack-Babel/HEAD/src/images/helloworld.gif
--------------------------------------------------------------------------------
/src/fonts/prototype.regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplySylvia/HowTo-React-Webpack-Babel/HEAD/src/fonts/prototype.regular.ttf
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | // [presets] allow us to define the additional packages we would like to include.
3 | // This will give us access to jsx and several other newer js features.
4 | "presets": ["@babel/preset-env","@babel/preset-react"]
5 | }
--------------------------------------------------------------------------------
/src/index.scss:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Prototype Regular';
3 | src: url('./fonts/prototype.regular.ttf') format("truetype");
4 | font-weight: 400;
5 | font-style: normal;
6 | }
7 |
8 | body {
9 | margin: 0;
10 | padding: 0;
11 | background-color: #1f1f1f;
12 | color: #f1f1f1;
13 | }
14 |
15 | h1 {
16 | font-family: 'Prototype Regular';
17 | }
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | browser: true,
4 | es2021: true,
5 | },
6 | extends: [
7 | 'plugin:react/recommended',
8 | 'airbnb',
9 | ],
10 | parser: "@babel/eslint-parser",
11 | parserOptions: {
12 | ecmaFeatures: {
13 | jsx: true,
14 | },
15 | ecmaVersion: 'latest',
16 | sourceType: 'module',
17 | },
18 | plugins: [
19 | 'react',
20 | ],
21 | rules: {
22 | },
23 | };
24 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | React App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | // import reactDOM from "react-dom"; Version 17~
3 | import { createRoot } from 'react-dom/client'; // version 18^
4 | import hello from './images/helloworld.gif';
5 | import './index.scss';
6 |
7 | function App() {
8 | return (
9 |
10 |
Hello World
11 |

12 |
13 | );
14 | }
15 |
16 | const root = createRoot(document.getElementById('root')); // version 18^
17 | // reactDOM.render(, document.getElementById("root")); Version 17~
18 | root.render(); // Version 18^
19 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const ESLintPlugin = require('eslint-webpack-plugin');
3 |
4 | module.exports = {
5 | mode: "development",
6 | entry: "./src/index.jsx",
7 | output: {
8 | path: path.join(__dirname, "public"),
9 | filename: "bundle.js",
10 | },
11 | module: {
12 | rules: [
13 | {
14 | test: /\.(jsx|js)$/,
15 | exclude: /node_modules/,
16 | loader: "babel-loader",
17 | },
18 | {
19 | test: /\.s[ac]ss$/i,
20 | use: ["style-loader", "css-loader", "sass-loader"],
21 | },
22 | {
23 | test: /\.(png|svg|jpg|jpeg|gif)$/i,
24 | type: "asset/resource",
25 | },
26 | {
27 | test: /\.(woff|woff2|eot|ttf|otf)$/i,
28 | type: 'asset/resource',
29 | },
30 | ],
31 | },
32 | devtool: "eval-cheap-module-source-map",
33 | devServer: {
34 | static: {
35 | directory: path.join(__dirname, "public"),
36 | },
37 | compress: true,
38 | port: 3000,
39 | },
40 | plugins: [new ESLintPlugin()],
41 | };
42 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react_from_scratch",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "dependencies": {
7 | "react": "^18.0.0",
8 | "react-dom": "^18.0.0"
9 | },
10 | "devDependencies": {
11 | "@babel/core": "^7.17.5",
12 | "@babel/eslint-parser": "^7.17.0",
13 | "@babel/preset-env": "^7.16.11",
14 | "@babel/preset-react": "^7.16.7",
15 | "babel-loader": "^8.2.3",
16 | "css-loader": "^6.7.1",
17 | "eslint": "^8.12.0",
18 | "eslint-config-airbnb": "^19.0.4",
19 | "eslint-plugin-import": "^2.25.4",
20 | "eslint-plugin-jsx-a11y": "^6.5.1",
21 | "eslint-plugin-react": "^7.29.4",
22 | "eslint-plugin-react-hooks": "^4.4.0",
23 | "eslint-webpack-plugin": "^3.1.1",
24 | "sass": "^1.49.9",
25 | "sass-loader": "^12.6.0",
26 | "style-loader": "^3.3.1",
27 | "webpack": "^5.70.0",
28 | "webpack-cli": "^4.9.2",
29 | "webpack-dev-server": "^4.7.4"
30 | },
31 | "scripts": {
32 | "start": "webpack --mode=development",
33 | "build": "webpack --mode=production",
34 | "dev": "webpack serve --open"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/bonus/image_assets_configuration.md:
--------------------------------------------------------------------------------
1 | # ✨ Image Assets Configuration
2 | By default webpack will not allow the module import of image assets. To allow this we will include a new rule to permit this.
3 |
4 | Inside webpack.config.js:
5 | ```js
6 | module: {
7 | rules: [
8 | {
9 | test: /\.(jsx|js)$/,
10 | exclude: /node_modules/,
11 | loader: "babel-loader",
12 | },
13 | {
14 | test: /\.s[ac]ss$/i,
15 | use: ["style-loader", "css-loader", "sass-loader"],
16 | },
17 | // our new rule to allow the import of image assets
18 | {
19 | test: /\.(png|svg|jpg|jpeg|gif)$/i,
20 | type: "asset/resource",
21 | },
22 | ],
23 | },
24 | ```
25 |
26 | With that set we can now import images into our files.
27 |
28 | Inside index.jsx:
29 | ```js
30 | import React from "react";
31 | import { createRoot } from "react-dom/client";
32 | const root = createRoot(document.getElementById("root"));
33 |
34 | import "./index.scss";
35 |
36 | import hello from "./images/helloworld.gif";
37 |
38 | const App = () => {
39 | return (
40 |
41 |
Hello World
42 |

43 |
44 | );
45 | };
46 |
47 | root.render();
48 | ```
49 |
--------------------------------------------------------------------------------
/bonus/custom_font_configuration.md:
--------------------------------------------------------------------------------
1 | # ✨ Custom Font Configuration
2 | By default webpack will not allow the import of custom font types. This allow this feature we will add a new fule to our configuration.
3 |
4 | Inside webpack.config.js:
5 | ```js
6 | module: {
7 | rules: [
8 | {
9 | test: /\.(jsx|js)$/,
10 | exclude: /node_modules/,
11 | loader: "babel-loader",
12 | },
13 | {
14 | test: /\.s[ac]ss$/i,
15 | use: ["style-loader", "css-loader", "sass-loader"],
16 | },
17 | {
18 | test: /\.(png|svg|jpg|jpeg|gif)$/i,
19 | type: "asset/resource",
20 | },
21 | // new rule to allow import of custom fonts
22 | {
23 | test: /\.(woff|woff2|eot|ttf|otf)$/i,
24 | type: 'asset/resource',
25 | },
26 | ],
27 | },
28 | ```
29 |
30 | Now that our webpack is setup we can import and create custom font faces.
31 |
32 | Inside index.css/.scss:
33 | ```css
34 | @font-face {
35 | font-family: 'Prototype Regular';
36 | src: url('./fonts/prototype.regular.ttf') format("truetype");
37 | font-weight: 400;
38 | font-style: normal;
39 | }
40 |
41 | body {
42 | margin: 0;
43 | padding: 0;
44 | background-color: #1f1f1f;
45 | color: #f1f1f1;
46 | }
47 |
48 | h1 {
49 | font-family: 'Prototype Regular';
50 | }
51 | ```
52 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 |
--------------------------------------------------------------------------------
/bonus/sass_configuration.md:
--------------------------------------------------------------------------------
1 | # ✨ Sass Configuration
2 | To leverage a css preprocessor we have to include additonal dependencies and add them to our configuration.
3 |
4 | ## Sass Dependencies
5 |
6 | - [sass-loader](https://www.npmjs.com/package/sass-loader) loads a Sass/SCSS file and compiles it to CSS.
7 | - [sass](https://www.npmjs.com/package/sass) css preprocessor.
8 |
9 | ```bash
10 | yarn add sass-loader sass --dev
11 | ```
12 |
13 | ## Sass Webpack Configuration
14 | Now that we have our dependencies installed we can tell webpack to leverge them for sass files.
15 |
16 | Inside webpack.config.js:
17 | ```js
18 | const path = require("path");
19 |
20 | module.exports = {
21 | mode: "development",
22 | entry: "./src/index.jsx",
23 | output: {
24 | path: path.join(__dirname, 'public'),
25 | filename: "bundle.js"
26 | },
27 | module: {
28 | rules: [
29 | {
30 | test: /\.(jsx|js)$/,
31 | exclude: /node_modules/,
32 | loader: "babel-loader"
33 | },
34 | /*
35 | Our original css test
36 | {
37 | test: /\.css$/,
38 | use: ['style-loader','css-loader']
39 | }
40 | */
41 | // new css test to include sass
42 | {
43 | // looks for sass OR css files on import
44 | test: /\.s[ac]ss$/i,
45 | use: [
46 | // Creates `style` nodes from JS strings
47 | "style-loader",
48 | // Translates CSS into CommonJS
49 | "css-loader",
50 | // Compiles Sass to CSS
51 | "sass-loader",
52 | ],
53 | },
54 | ]
55 | },
56 | devtool: "eval-cheap-module-source-map",
57 | devServer: {
58 | static: {
59 | directory: path.join(__dirname, 'public'),
60 | },
61 | compress: true,
62 | port: 3000,
63 | }
64 | }
65 | ```
66 |
67 | With this addition to our configuration we can now import sass files just like js files!
68 |
69 | Inside index.jsx:
70 | ```js
71 | import React from "react";
72 | import { createRoot } from "react-dom/client";
73 | const root = createRoot(document.getElementById("root"));
74 |
75 | // here is out import for our styles
76 | import "./index.scss";
77 |
78 | const App = () => {
79 | return Hello World
80 | }
81 |
82 | root.render();
83 | ```
--------------------------------------------------------------------------------
/bonus/eslint_configuration.md:
--------------------------------------------------------------------------------
1 | # ✨ Eslint Configuration
2 | Eslint is a great tool to help us as developers follow a style guide and ensure a consistent code base. Our linter will run on our files and output if we are ever not following these guidelines.
3 |
4 | ## Eslint Dependencies
5 | Our core dependency will be the [eslint package](https://www.npmjs.com/package/eslint). Now there are several optional packages you can install as dependencies depending on how you want to setup the linter. We will be leveraging the built in initilizer for this.
6 |
7 | ```bash
8 | yarn add eslint --dev
9 | ```
10 |
11 | ## Eslint Initilizer
12 | Once this has been installed we can through the setup process using the built in initilizer.
13 |
14 | ```bash
15 | yarn create @eslint/config
16 | ```
17 |
18 | This will start an interactive prompt just like `npm init` or `yarn init`.
19 |
20 | ### Step One
21 | In this first step we are choosing how we want to use eslint. This is up to your personal use case. For this example we will choose the most demanding use case.
22 |
23 | 
24 |
25 | ### Step Two
26 | This step sets how out import statements are configured. In react we are leveraging Javascript Modules so we will select this option.
27 |
28 | 
29 |
30 | ### Step Three
31 | This step is the framework selection. Since we are working in react we choose react here. This will let us install the correct dependencies through this tool.
32 |
33 | 
34 |
35 | ### Step Four
36 | This step tells the linter if we are using typescript. For this example we are not so we will choose no.
37 |
38 | 
39 |
40 | ### Step Five
41 | This step we are selection the enviroment our app will run. Since this is react a client side application we will choose browser.
42 |
43 | 
44 |
45 | ### Step Six
46 | If you want to follow a predefined style guide you can choose the use existing option OR you can go through a series of questions to define your own. For this example we will use a preexisting style guide.
47 |
48 | 
49 |
50 | ### Step Seven
51 | In this step we can select an existing style guide based on out previous selection. Here we will use the [airbnb style guide](https://github.com/airbnb/javascript) for this example.
52 |
53 | 
54 |
55 | ### Step Eight
56 | This step allows us to choose how we want our configuration file to be created. For this example we use the js version.
57 |
58 | 
59 |
60 | ### Step Nine
61 | This step allows choose if we want to install the additional dependencies to support the configurations we choose in the above steps. Here we will select yes.
62 |
63 | 
64 |
65 | ### Step Ten
66 | Here we are finally done! Our linter has been setup and is ready to use.
67 |
68 | >NOTE: eslint config only leverages npm to install the dependencies so some clean up is manual for yarn users.
69 | Delete the `package-lock.json` and run `yarn upgrade` to update the yarn lock file.
70 |
71 | 
72 |
73 |
74 | ### Current Directory
75 | ```
76 | App Directory
77 | ├── package.json
78 | ├── public
79 | │ ├── bundle.js
80 | │ └── index.html
81 | ├── src
82 | │ └── index.jsx
83 | ├── .babelrc
84 | ├── .eslintrc.js <= new config file
85 | ├── webpack.config.js
86 | └── yarn.lock
87 | ```
88 |
89 | ### Preview of linter in VsCode
90 | Our linter is now hard at work makign sure we are following the rules we set.
91 |
92 | 
93 |
94 | ## Enforce Eslint Rules
95 | Want to enforce these rules with webpack? We can do this with a little bit more setup.
96 |
97 | ### Additional Dependencies
98 |
99 | - [eslint-webpack-plugin](https://www.npmjs.com/package/eslint-webpack-plugin) to connect webpack and eslint together.
100 | - [@babel/eslint-parser](https://www.npmjs.com/package/@babel/eslint-parser) to add the ability to look at our existing eslint config.
101 |
102 | ```bash
103 | yarn add eslint-webpack-plugin @babel/eslint-parser --dev
104 | ```
105 |
106 | ### Add to webpack the new plugin.
107 |
108 | In webpack.config.js:
109 | ```js
110 | // at the top add this new import
111 | const ESLintPlugin = require('eslint-webpack-plugin');
112 | // inside the exports add a new field labels plugins
113 | module.exports = {
114 | // ...
115 | plugins: [new ESLintPlugin()],
116 | }
117 | ```
118 |
119 | ### Set eslint parser
120 |
121 | In .eslintrc.js:
122 | ```js
123 | module.exports = {
124 | env: {
125 | browser: true,
126 | es2021: true,
127 | },
128 | extends: [
129 | 'plugin:react/recommended',
130 | 'airbnb',
131 | ],
132 | // Here is our new parser option set to babel
133 | parser: "@babel/eslint-parser",
134 | parserOptions: {
135 | ecmaFeatures: {
136 | jsx: true,
137 | },
138 | ecmaVersion: 'latest',
139 | sourceType: 'module',
140 | },
141 | plugins: [
142 | 'react',
143 | ],
144 | rules: {
145 | },
146 | };
147 | ```
148 |
149 | And just like that now when you start up your server you will be forced to follow the rules you set in your configuration!
150 |
151 | 
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HOW TO: React Setup with Webpack and Babel
2 | In this breakdown we will be going over how to setup a react development enviroment from scratch. This enviroment will include Webpack and Babel for easy development that will include hot reloading.
3 |
4 | >NOTE: This repo contains the finialized code for this setup.
5 |
6 | ## Roadmap
7 | 1. Create source 📁 directories and 📝 files.
8 | 2. Install and setup 🧶 Yarn.
9 | 3. Install ⚙️ application dependencies.
10 | 4. Set up 📦 Webpack Configuration for bundeling.
11 | 5. Set up 🪄 Babel Configuration.
12 | 6. Set up Webpack Development Server for 🔥 hot reloading.
13 | ## ✨ Additional Configurations
14 | Beyond the initial setup of the react enviroment are a variety of additonal configurations that may be helpful in an enviroment.
15 |
16 | - [Sass Configuration](/bonus/sass_configuration.md)
17 | - [Image Assets Configuration](/bonus/image_assets_configuration.md)
18 | - [Custom Font Configuration](/bonus/custom_font_configuration.md)
19 | - [Eslint Configuration](/bonus/eslint_configuration.md)
20 |
21 | ## Create source 📁 directories and 📝 files.
22 | For our application we will create some starting directories and files.
23 |
24 | Inside of your project directory:
25 | ```bash
26 | mkdir src public && touch src/index.jsx public/index.html
27 | ```
28 |
29 | > NOTE: `src` will be the directory where we will hold all of our development code.`public` will be where our html and bundled js will go.
30 |
31 | #### Current Directory
32 | ```
33 | App Directory
34 | ├── public
35 | │ └── index.html
36 | └── src
37 | └── index.jsx
38 | ```
39 |
40 | We will need other files, but we will add them as we go. This would be a good time to create your .gitignore and set the default node ignores.
41 |
42 | Let's setup our base html file.
43 |
44 | Inside our index.html:
45 | ```html
46 |
47 |
48 |
49 |
50 |
51 |
52 | React App
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | ```
62 |
63 | > For now we will not do anything to the src/index.js. We will once we install the required dependencies for our application.
64 |
65 | ## Install and setup 🧶 Yarn.
66 | To manage our dependencies we will be using a package manager called 🧶 Yarn. You can learn more about it [here](https://yarnpkg.com/).
67 |
68 | ### Yarn Installation
69 | ```bash
70 | npm i -g yarn
71 | ```
72 |
73 | You can verify your install using `yarn --version` and you should get back a response similiar to `1.22.17`.
74 |
75 | ### Yarn Commands
76 |
77 | | Command | Description |
78 | |----------|--------------|
79 | | yarn init | Initializes the development of a package/application. |
80 | | yarn add | Adds a package to use in your current application. |
81 | | yarn add global | Adds a package to globally available directory. |
82 | | yarn add --dev | Adds a package to your current application under the development dependencies. |
83 | | yarn install | Installs all the dependencies defined in a package.json file. |
84 | | yarn remove | Removes an unused package from your current package. |
85 | | yarn [scriptname] | Runs a script defined in the package.json |
86 |
87 | For detailed information on the commands you can check the [docs](https://classic.yarnpkg.com/en/docs/cli/).
88 |
89 | ### Yarn customization
90 | Want to turn on emojis in yarn for a more fun output?
91 | ```bash
92 | yarn config set -- --emoji true
93 | ```
94 | There are a bunch of configurations available for yarn so check out the docs for options!
95 |
96 | ## Install ⚙️ application dependencies.
97 | Our next step is to install all the dependencies that our application and development enviroment will need.
98 |
99 | Before we can install anything we will need to initilize the directory as an node enviroment.
100 |
101 | ```bash
102 | yarn init -y
103 | ```
104 | This command will generate a package.json with default fields. If you wish to fill out all the fields manually you can run `yarn init`.
105 |
106 | Our application is now ready for our dependencies.
107 |
108 | ### React Dependancies
109 | - [React](https://www.npmjs.com/package/react) for ui component library.
110 | - [ReactDOM](https://www.npmjs.com/package/react-dom) for connecting the ui component library to the dom.
111 |
112 | ```bash
113 | yarn add react react-dom
114 | ```
115 | ### Webpack Dependancies
116 |
117 | - [webpack](https://www.npmjs.com/package/webpack) for bundling our code.
118 | - [webpack-cli](https://www.npmjs.com/package/webpack-cli) for terminal commands around bundling our code.
119 | - [webpack-dev-server](https://www.npmjs.com/package/webpack-dev-server) for hot reloading functionality.
120 |
121 | ```bash
122 | yarn add webpack webpack-cli webpack-dev-server --dev
123 | ```
124 | >NOTE: notice the `--dev` in the above command. We are installing these are development dependencies since these are only for development purposes and will not be included in our final production version.
125 |
126 | ### Babel Dependancies
127 |
128 | - [@babel/core](https://babeljs.io/docs/en/babel-core) for translations between js versions.
129 | - [@babel/preset-env](https://babeljs.io/docs/en/babel-preset-env) for latest support of js versions along with polyfils for browser support.
130 | - [@babel/preset-react](https://babeljs.io/docs/en/babel-preset-react) for react support that includes jsx.
131 |
132 | ```bash
133 | yarn add @babel/core @babel/preset-env @babel/preset-react --dev
134 | ```
135 |
136 | ### Loader Dependancies
137 | For hot loading with webpack-dev-server we will need to add the loaders we want to run. These are a few of the option that are available and the base options to start with.
138 |
139 | - [babel-loader](https://www.npmjs.com/package/babel-loader) to connect babel and webpack together.
140 | - [css-loader](https://www.npmjs.com/package/css-loader) to add support for css imports.
141 | - [style-loader](https://www.npmjs.com/package/style-loader) to add css injections to the dom.
142 |
143 | ```bash
144 | yarn add babel-loader css-loader style-loader --dev
145 | ```
146 |
147 | ### Final Dependencies
148 | Our final package.json should look something like this:
149 |
150 | ```json
151 | "dependencies": {
152 | "react": "^18.0.0",
153 | "react-dom": "^18.0.0"
154 | },
155 | "devDependencies": {
156 | "@babel/core": "^7.17.5",
157 | "@babel/preset-env": "^7.16.11",
158 | "@babel/preset-react": "^7.16.7",
159 | "babel-loader": "^8.2.3",
160 | "css-loader": "^6.7.1",
161 | "style-loader": "^3.3.1",
162 | "webpack": "^5.70.0",
163 | "webpack-cli": "^4.9.2",
164 | "webpack-dev-server": "^4.7.4"
165 | },
166 | ```
167 |
168 | > NOTE: Your version numbers might look different since packages update over time.
169 |
170 | #### Current Directory
171 | ```
172 | App Directory
173 | ├── package.json
174 | ├── public
175 | │ └── index.html
176 | ├── src
177 | │ └── index.jsx
178 | └── yarn.lock
179 | ```
180 |
181 | ## Set up 📦 Webpack Configuration for bundeling.
182 | Now it is time to setup our webpack configuration so our code can be bundled.
183 |
184 | To configure webpack we will need to create a `webpack.config.js`:
185 |
186 | ```bash
187 | touch webpack.config.js
188 | ```
189 |
190 | #### Current Directory
191 | ```
192 | App Directory
193 | ├── package.json
194 | ├── public
195 | │ └── index.html
196 | ├── src
197 | │ └── index.jsx
198 | ├── webpack.config.js
199 | └── yarn.lock
200 | ```
201 |
202 |
203 | Let's setup the default settings for our webpack configuration inside the file we just created.
204 |
205 | Inside webpack.config.js:
206 | ```js
207 | // For node to know our absolute file path we will be using the internal module path
208 | const path = require("path");
209 |
210 | // Our export here is the configuration webpack will use
211 | module.exports = {
212 | // [mode] will determine how our code will be bundled.
213 | // "development" will be human readable
214 | // "production" will be minified
215 | mode: "development",
216 | // [entry] this is the file where the bundling starts from.
217 | entry: "./src/index.jsx",
218 | // [output] is a configuration object to determine how and where to bundle our code
219 | output: {
220 | // [path] is where to output
221 | path: path.join(__dirname, 'public'),
222 | // [filename] is the name of the file
223 | filename: "bundle.js"
224 | }
225 | }
226 | ```
227 |
228 | With this setup in place we will be able to start using the webpack terminal command to bundle out code. At the moment our index.js is empty so let's change that.
229 |
230 | > If you are using React 18^
231 |
232 | Inside src/index.jsx:
233 |
234 | ```js
235 | // Bring React in to build a component.
236 | import React from "react";
237 | // Import from react-dom the ability to create a root render
238 | import { createRoot } from "react-dom/client";
239 | // create the root of the app by selection where the app should be mounted in the dom
240 | const root = createRoot(document.getElementById("root"));
241 |
242 | // Here is out base App component.
243 | // Notice we are NOT using jsx here. This is because we have not set up babel yet.
244 | const App = React.createElement("h1",null,"Hello World");
245 |
246 | // render the root element with the provided component
247 | root.render();
248 |
249 | ```
250 |
251 | > If you are using React 17~
252 |
253 | Inside src/index.jsx:
254 | ```js
255 | // Bring React in to build a component.
256 | import React from "react";
257 | // Bring reactDOM in to mount component to the dom.
258 | import reactDOM from "react-dom";
259 |
260 | // Here is out base App component.
261 | // Notice we are NOT using jsx here. This is because we have not set up babel yet.
262 | const App = React.createElement("h1",null,"Hello World");
263 |
264 | // Render our app to the dom mounted to the element with id of root inside our public/index.html file.
265 | reactDOM.render(App, document.getElementById("root"));
266 | ```
267 | > NOTE: We will be adding additional configuration to webpack as we go.
268 |
269 | To run our babel configuration let's make our life easy by adding a few scripts to our `package.json`.
270 |
271 | - `start` will tell webpack to bundle our code development.
272 | - `build` will tell webpack to bundle our code for production.
273 |
274 | Inside package.json:
275 | ```json
276 | {
277 | // ... all other fields
278 | "scripts": {
279 | "start": "webpack --mode=development",
280 | "build": "webpack --mode=production"
281 | }
282 | }
283 | ```
284 |
285 | To run these commands all you need to do is run `yarn [command]` replacing `[command]` with the script name you want to run.
286 |
287 | ```bash
288 | yarn start
289 | ```
290 |
291 | You should see an output from webpack bundling our code into the output file we specified in the `webpack.config.js` file we made earlier.
292 |
293 | #### Current Directory
294 | ```
295 | App Directory
296 | ├── package.json
297 | ├── public
298 | │ ├── bundle.js
299 | │ └── index.html
300 | ├── src
301 | │ └── index.jsx
302 | ├── webpack.config.js
303 | └── yarn.lock
304 | ```
305 | Now open your html file in the browser of your choice and we should see our `Hello World` message!
306 |
307 |
308 | > Want to learn more about webpack? Check out the [docs](https://webpack.js.org/).
309 |
310 | ## Set up 🪄 Babel Configuration.
311 | Now that webpack is set up we can configure babel to allow us to use more js features like jsx.
312 |
313 | To get started we need to create a .babelrc which is our config file.
314 |
315 | ```bash
316 | touch .babelrc
317 | ```
318 |
319 | #### Current Directory
320 | ```
321 | App Directory
322 | ├── package.json
323 | ├── public
324 | │ ├── bundle.js
325 | │ └── index.html
326 | ├── src
327 | │ └── index.jsx
328 | ├── .babelrc
329 | ├── webpack.config.js
330 | └── yarn.lock
331 | ```
332 |
333 |
334 | Inside .babelrc:
335 | ```js
336 | {
337 | // [presets] allow us to define the additional packages we would like to include.
338 | // This will give us access to jsx and several other newer js features.
339 | "presets": ["@babel/preset-env","@babel/preset-react"]
340 | }
341 | ```
342 |
343 | Now we are not quite ready to start using babel yet. We will need to configure webpack further to include it.
344 |
345 | Inside webpack.config.js:
346 | ```js
347 | const path = require("path");
348 |
349 | module.exports = {
350 | mode: "development",
351 | entry: "./src/index.jsx",
352 | output: {
353 | path: path.join(__dirname, 'public'),
354 | filename: "bundle.js"
355 | },
356 | // [module] will allow us to set any external modules we have added to webpack
357 | module: {
358 | // [rules] will determine the rules around those external modules
359 | rules: [
360 | // First rule is to idenify js and jsx files and turn on babel
361 | {
362 | test: /\.(jsx|js)$/,
363 | exclude: /node_modules/,
364 | loader: "babel-loader"
365 | },
366 | // Second rule is to check for css files and load them with the following loaders
367 | {
368 | test: /\.css$/,
369 | use: ['style-loader','css-loader']
370 | }
371 | ]
372 | },
373 | }
374 | ```
375 |
376 | Now we can use all the cool js features like jsx! Time to update our application.
377 |
378 | Inside src/index.jsx:
379 | ```js
380 | import { createRoot } from "react-dom/client";
381 | const root = createRoot(document.getElementById("root"));
382 |
383 | // Huzzah for jsx!
384 | const App = () => {
385 | return Hello World
386 | }
387 |
388 | root.render();
389 | ```
390 |
391 | Go ahead and run your `start` script and check it out!
392 |
393 | > Want to learn more about Babel? Check out the [docs](https://babeljs.io/).
394 |
395 | ## Set up Webpack Development Server for 🔥 hot reloading.
396 | Now its time to speed up our development process with hot reloading.
397 |
398 | To do this we will be using the webpack-dev-server that we installed. The configuration for the server will live in the webpack configuration file.
399 |
400 | Inside webpack.config.js:
401 | ```js
402 | const path = require("path");
403 |
404 | module.exports = {
405 | mode: "development",
406 | entry: "./src/index.jsx",
407 | output: {
408 | path: path.join(__dirname, 'public'),
409 | filename: "bundle.js"
410 | },
411 | module: {
412 | rules: [
413 | {
414 | test: /\.(jsx|js)$/,
415 | exclude: /node_modules/,
416 | loader: "babel-loader"
417 | },
418 | {
419 | test: /\.css$/,
420 | use: ['style-loader','css-loader']
421 | }
422 | ]
423 | },
424 | // [devtool] this is an additional source map that will let the browser know what files are running our code.
425 | // Helps with error tracing. Without it we will not know where our errors are coming from because it will state that everything inside the bundle file.
426 | devtool: "eval-cheap-module-source-map",
427 | // [devServer] configuration for the live server including port
428 | devServer: {
429 | // [static] config for how what to serve
430 | static: {
431 | directory: path.join(__dirname, 'public'),
432 | },
433 | compress: true,
434 | // [port] what port on our local machine to run the dev server
435 | port: 3000,
436 | }
437 | }
438 | ```
439 |
440 | Now that we that we have our development server configured let's add a script to make it easy to run.
441 |
442 | Inside package.json:
443 | ```json
444 | // ...
445 | "scripts": {
446 | "start": "webpack --mode=development",
447 | "build": "webpack --mode=production",
448 | // our new script to start up our development server
449 | "dev": "webpack serve --open"
450 | },
451 | ```
452 |
453 | Now all we have to do to spin up our server is to run:
454 | ```bash
455 | yarn dev
456 | ```
457 | To view your server head on over to `localhost:3000` in your browser.
458 |
459 | And just like that we are off to the races! Enjoy and..
460 |
461 | ### Happy Hacking! 💻
--------------------------------------------------------------------------------