ReactJS: n käyttö Webpack 4: n, Babel 7: n ja materiaalisuunnittelun kanssa

Viime vuoden ja joidenkin ajan olen työskennellyt Reactin kanssa Creative Timissä. Olen käyttänyt create-reagoi-sovellusta hienojen tuotteiden kehittämiseen. Paljon asiakkaita on kysynyt, kuinka joku voi siirtää tuotemallimme Webpackiin.

Joten useiden pyyntöjen jälkeen loimme tämän pienen opetusohjelman siitä, miten React with Webpack 4: n ja Babel 7: n kanssa aloitetaan. Opetusohjelman lopussa aion näyttää teille, kuinka voit lisätä Material Dashboard Reactin vasta uusien luotu sovellus.

Ennen kuin aloitamme, varmista, että koneellesi on asennettu uusimmat npm- ja Nodejs-versiot. Tämän viestin kirjoittamisen hetkellä uusimmat versiot olivat koneellani 6.4.1 npm: lle ja 8.12.0 (lts) Nodejs: lle.

Uuden projektikansion luominen paketilla package.json

Ensinnäkin, luodaan uusi kansio uudelle sovelluksellemme ja syötä se:

mkdir react-webpack-babel-tutorialcd react-webpack-babel-tutorial

Nyt kun olemme luoneet kansion , johon aiomme kehittää sovelluksen , meidän on lisättävä siihen package.json- tiedosto. Voimme tehdä tämän kahdella tavalla, ja sinun pitäisi valita yksi niistä:

  1. luo vain package.json- tiedosto ilman muita asetuksia:
npm init -y

Kuten näette, package.json- tiedosto on luotu, ja siinä on joitain perustietoja.

2. luo tiedosto package.json muutamilla määritysasetuksilla

npm init

Olen lisännyt joitain juttuja äskettäin luotuun package.json- tiedostoon, kuten hienoja avainsanoja , repo ja niin edelleen.

Tämän jälkeen lisätään index.html- ja index.js- tiedostot uuteen projektikansioon, src- kansion sisälle .

  1. Linux / MacOS-komennot
mkdir srctouch src/index.htmltouch src/index.js

2. Windows-komennot

mkdir srcecho "" > src\index.htmlecho "" > src\index.js

Tämän jälkeen lisätään seuraava malli index.html: n sisälle .

     React Tutorial    You need to enable JavaScript to run this app. 

Lisätään jotain index.js: n sisälle vain jonkin esittelyn vuoksi, jonka aiomme nähdä hieman alaspäin.

(function () { console.log("hey mister");}());

Ja tämän olemme saaneet tähän mennessä:

Webpackin lisääminen projektiin

Aloitetaan kaikkien Webpack- pakettien lisääminen , joita tarvitsemme. Aiomme asentaa ne devDependenciesiksi, koska niitä käytetään vain kehitystilassa.

npm install --save-dev webpack webpack-cli webpack-dev-server
  • verkkopakkaus

    - käytetään uuden sovelluksemme määrittämiseen

    - tämän viestin julkaisuhetkellä versio oli 4.19.0

  • webpack-cli

    - käytetään, jotta voimme käyttää Webpackia komentorivillä

    - tämän viestin julkaisuhetkellä versio oli 3.1.0

  • webpack-dev-palvelin

    - käytetään niin, että kun muutamme tiedostoa uudessa sovelluksessamme, meidän ei tarvitse päivittää sivua. Se päivittää selainsivun automaattisesti aina, kun muutamme tiedostoa sovelluksessamme

    - kuten nimensä mukaan palvelin toimii jatkuvasti

    - tämän viestin julkaisuhetkellä versio oli 3.1.8

Jos katsomme package.json- tiedoston sisälle , näemme, että nämä kolme pakettia lisättiin tähän tiedostoon näin:

"devDependencies": { "webpack": "^4.19.0", "webpack-cli": "^3.1.0", "webpack-dev-server": "^3.1.8"}

Aion mennä eteenpäin ja poistaa ^ (caret) jokaisesta versiosta. Tämä johtuu siitä, etten voi kertoa, toimiiko näiden laajennusten seuraava versio edelleen rakentamani kanssa. Mielestäni tämän pitäisi olla järkeä. Käytä uutta sovellusta luodessasi käytettävissä olevia versioita ja ehkä päivitä sitten uudempia versioita. Et ehkä tiedä, mikä uusi versio rikkoo sovellustasi.

Kuten näette, näiden laajennusten asennus teki joitain muutoksia projektikansioon. Se lisäsi siihen node_modules- kansion ja package-lock.json .

Nyt meidän täytyy lisätä uusi tiedosto projektimme, config tiedosto webpack nimeltään webpack.config.js :

  1. Linux / MacOS-komento
touch webpack.config.js

2. Windows-komento

echo "" > webpack.config.js

Tai voit yksinkertaisesti luoda uuden tiedoston manuaalisesti, jos et halua käyttää komentoriviä.

Ennen kuin siirrymme eteenpäin ja aloitamme sekoittamisen Webpack-määritystiedostoon , asennetaan ensin joitain tarvitsemiamme sovelluksemme.

Ensinnäkin aiomme työskennellä joidenkin polkujen kanssa Webpack-määritystiedostossa. Asennetaan polku projektiimme devDependency-ominaisuutena.

npm install --save-dev path

Also, since we don’t want to manually inject the index.js file inside the HTML one, we are going to need a plugin called html-webpack-plugin. This plugin will inject the index.js inside the HTML file without any manual operation.

npm install --save-dev html-webpack-plugin

Once again, I am going to edit my package.json file and delete all the ^ (caret) occurrences from it.

One more edit that we are going to make to our package.json is to add some new scripts inside the scripts object, after the test script (See the second example below).

"webpack": "webpack","start": "webpack-dev-server --open"

This is what your package.json should look like at this point:

{ "name": "react-webpack-babel-tutorial", "version": "1.0.0", "description": "This is a Tutorial to showcase the usage of React with Webpack and Babel", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "webpack": "webpack", "start": "webpack-dev-server --open" }, "repository": { "type": "git", "url": "git+//github.com/creativetimofficial/react-webpack-babel-tutorial.git" }, "keywords": [ "react", "webpack", "babel", "creative-tim", "material-design" ], "author": "Creative Tim 
    
      (//www.creative-tim.com/)", "license": "MIT", "bugs": { "url": "//github.com/creativetimofficial/react-webpack-babel-tutorial/issues" }, "homepage": "//github.com/creativetimofficial/react-webpack-babel-tutorial#readme", "devDependencies": { "html-webpack-plugin": "3.2.0", "path": "0.12.7", "webpack": "4.19.0", "webpack-cli": "3.1.0", "webpack-dev-server": "3.1.8" }}
    

Let’s go ahead and run these commands one by one and see what happens.

npm run webpack

Webpack will automatically take the src/index.js file, compile it, and output it inside dist/main.js and will minify that code. This is because we haven’t yet configured the Webpack config file. Also, since we haven’t configured the file, we are going to have some warnings in our console.

If we run the other command

npm start

webpack-dev-server will automatically start a server and open the default browser with this server. But once again, since we do not have our webpack.config.js file configured, the output will not be the expected one.

If you want to stop the server, just press at the same time the CTRL + C keys while in the command line.

Let’s add the following template inside our Webpack config file:

const path = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = { entry: path.join(__dirname,'src','index.js'), output: { path: path.join(__dirname,'build'), filename: 'index.bundle.js' }, mode: process.env.NODE_ENV || 'development', resolve: { modules: [path.resolve(__dirname, 'src'), 'node_modules'] }, devServer: { contentBase: path.join(__dirname,'src') }, plugins: [ new HtmlWebpackPlugin({ template: path.join(__dirname,'src','index.html') }) ]};
  • entry and output

    — these are used to tell our server what has to be compiled and from where (entry: path.join(__dirname,’src’,’index.js’),). It also tells where to put the outputted compiled version (output — the folder and the filename)

  • mode

    — this is the mode of our output. We are setting it to ‘development’. If in the scripts we specify the NODE_ENV variable, it will take that one instead. See the below example on how to use NODE_ENV (note that the below changes will not be made inside the package.json file in this tutorial, it is just an example for you to see how it works)

"webpack": "NODE_ENV=production webpack",
  • resolve

    — this is used so that we can import anything from src folder in relative paths instead of absolute ones. It is the same for the node_modules. We can import anything from node_modules directly without absolute paths

  • devServer

    — this tells the webpack-dev-server what files are needed to be served. Everything from our src folder needs to be served (outputted) in the browser

  • plugins

    — here we set what plugins we need in our app. As of this moment we only need the html-webpack-plugin which tells the server that the index.bundle.js should be injected (or added if you will) to our index.html file

If we now run the earlier commands we will see some differences.

npm run webpack

We’ve changed where the output should be (from dist folder to build folder). By changing the mode of Webpack, now the code has a different look. It is not minified as the last time with no config.

npm start

The webpack-dev-server took everything from the src folder and outputted it to our browser.

We are on the right path, but we’ve only added Webpack to our project. Where are React and Babel? Well, that is what we are going to do next.

React, Babel and some nice loaders for styles

Add React and ReactDOM to our project as normal dependencies.

npm install --save react react-dom

At this moment in our development, if we were to add React code inside our JS file, Webpack will give us an error. It doesn’t know how to compile React inside the bundle.js file.

Let’s modify the index.js file as follows:

import React from "react";import ReactDOM from "react-dom";let HelloWorld = () => { return 

Hello there World!

}ReactDOM.render( , document.getElementById("root"));

And after that let’s start the server again.

npm start

And this is the error:

So this is where Babel comes to our aid. Babel will tell Webpack how to compile our React code.

Let’s go ahead and add a bunch of Babel packages to our app as devDependencies.

npm install --save-dev @babel/core @babel/node @babel/preset-env @babel/preset-react babel-loader
  • @babel/core

    — this is used to compile ES6 and above into ES5

  • @babel/node

    — this is used so that we can import our plugins and packages inside the webpack.config.js rather than require them (it’s just something that I like, and maybe you’ll like it too)

  • @babel/preset-env

    — this will determinate which transformations or plugins to use and polyfills (i.e it provides modern functionality on older browsers that do not natively support it) based on the browser matrix you want to support

  • @babel/preset-react

    — this is going to compile the React code into ES5 code

  • babel-loader

    — this is a Webpack helper that transforms your JavaScript dependencies with Babel (i.e. will transform the import statements into require ones)

Since you are probably going to need to add some styles to your project (I know that I need them), we are going to add a loader that will let us import and use CSS files and SCSS files.

npm install --save-dev style-loader css-loader sass-loader node-sass
  • style-loader

    — this will add to the DOM the styles (will inject a le> tag insid e the HTML file)

  • css-loader

    — will let us import CSS files into our project

  • sass-loader

    — will let us import SCSS files into our project

  • node-sass

    — will compile the SCSS files into normal CSS files

We are going to create a new SCSS file and add it to our folders.

  1. Linux/MacOS command
touch src/index.scss

2. Windows command

echo "" > src/index.scss

And also add some nice styles to it.

body { div#root{ background-color: #222; color: #8EE4AF; }}

And change our index.js by adding an import for the SCSS file.

import React from "react";import ReactDOM from "react-dom";
// this line is new// we now have some nice styles on our react appimport "index.scss";
let HelloWorld = () => { return 

Hello there World!

}
ReactDOM.render( , document.getElementById("root"));

Don’t forget to delete the carets (^) from package.json.

This is how your package.json should look like:

{ "name": "react-webpack-babel-tutorial", "version": "1.0.0", "description": "This is a Tutorial to showcase the usage of React with Webpack and Babel", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "webpack": "webpack", "start": "webpack-dev-server --open" }, "repository": { "type": "git", "url": "git+//github.com/creativetimofficial/react-webpack-babel-tutorial.git" }, "keywords": [ "react", "webpack", "babel", "creative-tim", "material-design" ], "author": "Creative Tim 
     
       (//www.creative-tim.com/)", "license": "MIT", "bugs": { "url": "//github.com/creativetimofficial/react-webpack-babel-tutorial/issues" }, "homepage": "//github.com/creativetimofficial/react-webpack-babel-tutorial#readme", "devDependencies": { "@babel/core": "7.0.1", "@babel/node": "7.0.0", "@babel/preset-env": "7.0.0", "@babel/preset-react": "7.0.0", "babel-loader": "8.0.2", "css-loader": "1.0.0", "html-webpack-plugin": "3.2.0", "node-sass": "4.9.3", "path": "0.12.7", "sass-loader": "7.1.0", "style-loader": "0.23.0", "webpack": "4.19.0", "webpack-cli": "3.1.0", "webpack-dev-server": "3.1.8" }, "dependencies": { "react": "16.5.1", "react-dom": "16.5.1" }}
     

If we run any of the above commands again, the error will still persist. We haven’t yet told Webpack that it should use Babel and the style loaders to compile our React and SCSS code.

Next thing to do is add a configuration file for Babel. For this we need to create a file named .babelrc in which we will configure Babel.

I’ve heard that you can add the configuration for Babel directly in the webpack.config.js file. For this, you can take a look at the official babel-loader docs. As far as I am concerned, I think it’s best to have the Babel config in its own file. That way you do not overcrowd your Webpack config.

So, let’s run in the command line the following:

  1. Linux/MacOS command
touch .babelrc

2. Windows command

echo "" > .babelrc

And add the following code inside .babelrc so that babel-loader will know what to use to compile the code:

{ "presets": [ "@babel/env", "@babel/react" ]}

After these steps, we will need to add something to our project so we can import all sorts of files such as images. We will also need to add a plugin that will let us work with classes and much more. Let us add class properties in our classes. Basically, it will let us work with Object Oriented Programming — nice.

npm install --save-dev file-loader @babel/plugin-proposal-class-properties

Now that we have done this, we need to make some changes inside webpack.config.js so that Webpack will now use Babel. We’ll also configure Webpack to listen for style files and we are going to change the require statements to import ones.

So this being said, let’s change our webpack.config.js to the following (I’ve also added some comments, maybe they will help you):

// old// const path = require('path');// const HtmlWebpackPlugin = require('html-webpack-plugin');// newimport path from 'path';import HtmlWebpackPlugin from 'html-webpack-plugin';module.exports = { entry: path.join(__dirname,'src','index.js'), output: { path: path.join(__dirname,'build'), filename: 'index.bundle.js' }, mode: process.env.NODE_ENV || 'development', resolve: { modules: [path.resolve(__dirname, 'src'), 'node_modules'] }, devServer: { contentBase: path.join(__dirname,'src') }, module: { rules: [ // this is so that we can compile any React, // ES6 and above into normal ES5 syntax test: /\.(js, scss)$/, use: [ "style-loader", // creates style nodes from JS strings "css-loader", // translates CSS into CommonJS "sass-loader" // compiles Sass to CSS, using Node Sass by default ] , svg)$/, loaders: ['file-loader'] ] }, plugins: [ new HtmlWebpackPlugin({ template: path.join(__dirname,'src','index.html') }) ]};

There’s one more change we need to do to the package.json file. We need to tell our scripts that inside the config files of Webpack, we use import instead of require statements. Else it will give us an error that it doesn’t know what import stands for.

{ "name": "react-webpack-babel-tutorial", "version": "1.0.0", "description": "This is a Tutorial to showcase the usage of React with Webpack and Babel", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "webpack": "babel-node ./node_modules/webpack/bin/webpack", "start": "babel-node ./node_modules/webpack-dev-server/bin/webpack-dev-server --open" }, "repository": { "type": "git", "url": "git+//github.com/creativetimofficial/react-webpack-babel-tutorial.git" }, "keywords": [ "react", "webpack", "babel", "creative-tim", "material-design" ], "author": "Creative Tim (//www.creative-tim.com/)", "license": "MIT", "bugs": { "url": "//github.com/creativetimofficial/react-webpack-babel-tutorial/issues" }, "homepage": "//github.com/creativetimofficial/react-webpack-babel-tutorial#readme", "devDependencies": { "@babel/core": "7.0.1", "@babel/node": "7.0.0", "@babel/plugin-proposal-class-properties": "7.0.0", "@babel/preset-env": "7.0.0", "@babel/preset-react": "7.0.0", "babel-loader": "8.0.2", "css-loader": "1.0.0", "file-loader": "2.0.0", "html-webpack-plugin": "3.2.0", "node-sass": "4.9.3", "path": "0.12.7", "sass-loader": "7.1.0", "style-loader": "0.23.0", "webpack": "4.19.0", "webpack-cli": "3.1.0", "webpack-dev-server": "3.1.8" }, "dependencies": { "react": "16.5.1", "react-dom": "16.5.1" }}

Another thing that we will have to still add is the @babel/plugin-proposal-class-properties to the .babelrc file. Babel will know how to deal with class properties.

{ "presets": [ "@babel/env", "@babel/react" ], "plugins": [ "@babel/plugin-proposal-class-properties" ]}

Now we are done. We can run either one of the above commands and it should not give us any errors. Let’s see them in action.

npm run webpack

And now let’s see the main script of our app.

npm start

Add Material Design to our new React with Webpack and Babel project

As I’ve told you at the beginning of this post, we are not going to create from scratch styles for Material Design. That would require a lot of work. We don’t have time for that.

Instead, we are going to add a nice product that implements Google’s Material Design with some minor touches from the Creative Tim staff. We are going to add Material Dashboard React to it.

First things first, you need to get the product. Here are a few ways of getting the product:

  • Clone the repo inside another folder:
git clone //github.com/creativetimofficial/material-dashboard-react.git
  • Download from Github
  • Download from Creative Tim

Ok, so now we have both projects — Material Dashboard React and our newly created one with Webpack and Babel — with React.

Now, we can’t simply copy the src folder from Material Dashboard React into our new project. That will give us a lot of errors. Such as errors for missing dependencies, module not found, you get the point, a lot of errors.

So, I suggest that we start with adding the dependencies from Material Dashboard React’s package.json to our package.json. We do not need all the dependencies from Material Dashboard React’s packages, since we have built our own server using Webpack. We have added other style loaders beyond what the product has.

So this being said, we need the following:

npm install --save @material-ui/[email protected] @material-ui/[email protected] @types/[email protected] @types/[email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]

We are not going through all of them. They can be found on npmjs.com with all the details and their own documentation.

Once again, we go inside the package.json file and delete the carets (^) from the packages that we just installed.

Ok, we are almost done. We are going to copy all the contents of the src folder from Material Dashboard React inside our project’s src folder and override the index.js file. But keep it in the index.html file.

Now we need to add some styles and fonts cdns inside our index.html.

         React Tutorial    You need to enable JavaScript to run this app. 

And we are almost there. We still have a small problem. When we refresh the page, we have an error Cannot GET /dashboard. If we navigate to another page we will get, for example, Cannot GET /user and so on. So basically, our routes do not work. We need to make some changes inside either src/index.js or inside our webpack.config.js.

I will choose the first option since it is pretty straightforward and easy to understand.

We navigate inside the new index.js and we change the history type. We put createHashHistory() instead of createBrowserHistory().

This will allow us to refresh the page without any other errors. Now we are done.

import React from "react";import ReactDOM from "react-dom";import { createHashHistory } from "history";import { Router, Route, Switch } from "react-router-dom";import "assets/css/material-dashboard-react.css?v=1.5.0";import indexRoutes from "routes/index.jsx";const hist = createHashHistory();ReactDOM.render(   {indexRoutes.map((prop, key) => { return ; })}  , document.getElementById("root"));

I really hope you’ve liked this tutorial and I am very keen on hearing your thoughts about it. Just give this thread a comment and I’ll be more than happy to reply.

Special thanks should also go to Linh Nguyen My for her tutorial which has given me some much needed understanding on Webpack.

Useful links:

  • Get the code for this tutorial from Github
  • Read more about ReactJS on their official website
  • Read more about Webpack here
  • Read more about Babel on this link here
  • Read more about Material Design
  • Check out our platform to see what we are doing and who we are
  • Get Material Dashboard React from www.creative-tim.com or from Github
  • Read more about Material-UI, the core of Material Dashboard React

Find me on:

  • Email: [email protected]
  • Facebook: //www.facebook.com/NazareEmanuel
  • Instagram: //www.instagram.com/manu.nazare/