使用 webpack 4 和 Babel 7 构建 React 应用及如何引入 Material Design

图片描述

想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你!css

在过去的一年和一些人中,我一直在与 Creative Tim 合做。 我一直在使用 create-react-app 来开发一些不错的产品。 有不少客户询问如何在 Webpack 上迁移咱们的产品模板。html

在屡次要求求以后,咱们写了这个关于如何开始使用 React with Webpack 4和 Babel 7 的小教程。在本教程的最后,将向你们展现如何在新建立的应用程序上添加 Material Dashboard React前端

在咱们开始以前,请确保你的电脑上安装了 npmNodejs 的最新版本。在撰写本文时,个人电脑上的最新版本是 npm 的 6.4.1 和 Nodejs 的 8.12.0 (lts)。node

创建项目

首先,建立工程目录:react

mkdir react-webpack-babel-tutorial
cd react-webpack-babel-tutorial

如今咱们已经建立了咱们要开发应用程序的文件夹,接着须要添加一个 package.json 文件。 有两种建立方式,你能够选择其中的一种:webpack

1.只需建立 package.json 文件,无需任何其余配置:git

npm init -y

以下所示,package.json 文件已建立,其中包含一些很是基本的信息。github

clipboard.png

2.使用一些额外的配置设置建立 package.json 文件web

npm init

我在咱们新建立的 package.json 文件中添加了一些东西,好比一些很好的 keywords,一个repo等等...npm

图片描述

图片描述

以后,在根目录下建立 src 文件夹,而后在 src 下分别建立 index.htmlindex.js.

1.Linux / MacOS 命令

mkdir src
touch src/index.html
touch src/index.js

2.Windows 命令

mkdir src
echo "" > src\index.html
echo "" > src\index.js

建立完后在 index.html 添加如下内容。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <title>React Tutorial</title>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.
    -->
  </body>
</html>

接着在 index.js 中添加一些内容,目前只是为了展现一些内容,下面继续完善。

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

此时,目录结构以下:

图片描述

将 Webpack 添加到项目中

安装 Webapck 及所需的开发环境依赖模块。

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

    • 用来配置咱们的新应用
    • 本文所用的版本是 4.19.0
  • webpack-cli

    • 能够在命令行中使用 Webpack 了
    • 本文所用的版本是 3.1.0
  • webpack-dev-server

    • 这样,当咱们对新应用程序中的文件进行更改时,就不须要刷新页面了。每当咱们在应用程序中更改文件时,它会自动刷新浏览器页面
    • 本文所用的版本是 3.1.8

图片描述

看一下package.json文件,将看到这三个包被添加到这个文件中,以下所示:

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

补充说明一下版本号前的 ^,~ 的区别

  1. 指定版本:好比"webpack": "4.19.0",表示安装 4.19.0 的版本
  2. 波浪号 ~ 指定版本:好比 "webpack-cl": "~3.1.0",表示安装 3.1.0 的最新版本(不低于1.1.0),可是不安装 1.2.x,也就是说安装时不改变大版本号和次要版本号
  3. ^ 指定版本:好比 "webpack-dev-server": "^3.1.8",,表示安装 请输入代码3.1.4 及以上的版本,可是不安装4.0.0,也就是说安装时不改变大版本号。

package.json 文件只能锁定大版本,也就是版本号的第一位,并不能锁定后面的小版本,你每次 npm install 都是拉取的该大版本下的最新的版本,为了稳定性考虑咱们几乎是不敢随意升级依赖包的,这将致使多出来不少工做量,测试/适配等,因此 package-lock.json 文件出来了,当你每次安装一个依赖的时候就锁定在你安装的这个版本。

因此当咱们 npm install 安装完插件后,都会生成两个文件一个是 node_modulespackage-lock.json

图片描述

这里为了版本的一致性,我把 package.json 里的 版本号前面 ^ 删除了。

接着新建 Webpack 配置文件 webpack.config.js

1.Linux/MacOS 命令

touch webpack.config.js

2.Windows 命令

echo "" > webpack.config.js

若是你不想使用命令行,也能够简单地手动建立文件。

在开始处理 Webpack 配置文件以前,先在应用程序中安装一些咱们须要的东西。

首先安装 path 做为开发环境的路径依赖。

npm install --save-dev path

此外,因为不想在 HTML 中手动注入 index.js 文件,所以须要安装 html-webpack-plugin 的插件。 此插件经过配置在 HTML 文件中注入 index.js,无需手动操做。

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

再次,我将 package.json 文件删除全部 ^

安装完后在 package.json 文件中的 scripts 属性里添加觉得内容:

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

如今 package.json 内容以下:

{
  "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+https://github.com/creativetimofficial/react-webpack-babel-tutorial.git"
  },
  "keywords": [
    "react",
    "webpack",
    "babel",
    "creative-tim",
    "material-design"
  ],
  "author": "Creative Tim <hello@creative-tim.com> (https://www.creative-tim.com/)",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/creativetimofficial/react-webpack-babel-tutorial/issues"
  },
  "homepage": "https://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"
  }
}

接着运行如下命令,看看会发生什么:

npm run webpack

Webpack 将自动获取 src/index.js 文件,编译它,并将其输出到 dist/main.js 中,并压缩代码。这是由于咱们尚未配置 Webpack 配置文件。此外,因为咱们尚未配置该文件,我控制台中将出现一些警告。

图片描述

图片描述

图片描述

若是咱们运行以下命令:

npm start

webpack-dev-server 将自动启动服务器并使用该服务器打开默认浏览器。可是,因为咱们没有配置webpack.config.js 文件,因此页面展现并非咱们想要的内容。

图片描述

图片描述

若是想中止服务,只需在命令行中同时按下 CTRL + C 键。

接着在 webpack.config.js 添加如下内容:

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')
    })
  ]
};

1.entry

entry 能够是个字符串或数组或者是对象。 当 entry 是个字符串的时候,用来定义入口文件:

entry: './js/main.js'

当 entry 是个数组的时候,里面一样包含入口js文件,另一个参数能够是用来配置webpack提供的一个静态资源服务器,webpack-dev-server。webpack-dev-server 会监控项目中每个文件的变化,实时的进行构建,而且自动刷新页面:

entry: [
     'webpack/hot/only-dev-server',
     './js/app.js'
]

当 entry 是个对象的时候,咱们能够将不一样的文件构建成不一样的文件,按需使用,好比在个人 hello 页面中只要\ 引入 hello.js 便可:

entry: {
     hello: './js/hello.js',
     form: './js/form.js'
 }

2.output

output 参数是个对象,用于定义构建后的文件的输出。其中包含 path 和 filename:

output: {
     path: './build',
     filename: 'bundle.js'
 }

3.mode

这是输出的模式,这里将其 mode 设置为 “development”。若是在脚本中指定 NODE_ENV 变量,那么它将使用这个变量。请参阅下面关于如何使用 NODE_ENV 的示例(请注意,本教程中的 package.json 文件中不会进行如下更改,这只是一个示例,能够看到它是如何工做的)

"webpack": "NODE_ENV=production webpack",

4.resolve

webpack 在构建包的时候会按目录的进行文件的查找,resolve 属性中的 extensions 数组中用于配置程序能够自行补全哪些文件后缀:

resolve:{
  extensions:['','.js','.json']
}

5.devServer

这告诉 webpack-dev-server 须要提供哪些文件。 这里是 src 文件夹中的全部内容都须要在浏览器中浏览。

6.plugins

在这里,咱们设置了咱们的应用程序中须要的插件。到目前为止,只须要 html-webpack-plugin,它告诉服务器 index.bundl.js 应该被注入到 index.html 文件中

再次运行如下命令,显示会跟上一次不一样:

npm run webpack

图片描述

图片描述
图片描述

webpack-dev-server 从 src 文件夹中读取全部内容并输出到咱们的浏览器中。

配置 React,Babel 与 styles loaders

经过运行如下命令来引入 React :

npm i react react-dom --save-dev

在咱们的开发过程当中,若是咱们在 JS 文件中添加React代码,Webpack 会给咱们一个错误,它不知道如何在bundle.js 文件中编译 React

修改 index.js 内容以下:

import React from "react";
import ReactDOM from "react-dom";

let HelloWorld = () => {
  return <h1>Hello there World!</h1>
}

ReactDOM.render(
  <HelloWorld/>,
  document.getElementById("root")
);

再次运行如下命令:

npm start

错误以下:

图片描述

图片描述

因此这就是 Babel 出现的缘由, Babel 将告诉 Webpack 如何编译 React 代码。

安装 Babel 相关依赖:

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

@babel/core

这是将ES6及以上版本编译成ES5

@babel/node

babel-nodebabel-cli 的一部分,它不须要单独安装。

它的做用是在 node 环境中,直接运行 es2015 的代码,而不须要额外进行转码。例如咱们有一个 js 文件以 es2015 的语法进行编写(如使用了箭头函数)。咱们能够直接使用 babel-node es2015.js 进行执行,而不用再进行转码了。

能够说:babel-node = babel-polyfill + babel-register

@babel/preset-react

这个是把 React 代码编译成 ES5 代码。

babel-loader

babel-cli 同样,babel-loader 也会读取 .babelrc 或者 package.json 中的 babel 段做为本身的配置,以后的内核处理也是相同。惟一比 babel-cli 复杂的是,它须要和 webpack 交互,所以须要在 webpack 这边进行配置。比较常见的以下:

module: {
  rules: [
    {
      test: /\.js$/,
      exclude: /(node_modules|bower_components)/,
      loader: 'babel-loader'
    }
  ]
}

若是想在这里传入 babel 的配置项,也能够把改为:

// loader: 'babel-loader' 改为以下:
use: {
  loader: 'babel-loader',
  options: {
    // 配置项在这里
  }
}

咱们须要为项目中添加一些样式,此时就须要使用样式相关的加载器,这边使用 scss,安装命令以下:

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

style-loader

经过注入 <style> 标签将 CSS 添加到 DOM

css-loader

css-loader用于将 css 文件打包到js中, 经常配合 style-loader 一块儿使用,将 css 文件打包并插入到页面中

sass-loader

加载 SASS/SCSS 文件

node-sass

SCSS 文件编译为 CSS 文件

src 下建立 scss 文件:

1.Linux/MacOS 命令

touch src/index.scss

2.window 命令

echo "" > src/index.scss

并添加如下内容:

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

接着导入 index.js

import React from "react";
    import ReactDOM from "react-dom";
    // this line is new
    // we now have some nice styles on our react app
    import "index.scss";
    let HelloWorld = () => {
      return <h1>Hello there World!</h1>
    }
    ReactDOM.render(
      <HelloWorld/>,
      document.getElementById("root")
    );

记得删除 package.json 中的 ^ 号,内容以下:

{
      "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+https://github.com/creativetimofficial/react-webpack-babel-tutorial.git"
      },
      "keywords": [
        "react",
        "webpack",
        "babel",
        "creative-tim",
        "material-design"
      ],
      "author": "Creative Tim <hello@creative-tim.com> (https://www.creative-tim.com/)",
      "license": "MIT",
      "bugs": {
        "url": "https://github.com/creativetimofficial/react-webpack-babel-tutorial/issues"
      },
      "homepage": "https://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-loa

der": "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"
  }
}

若是咱们再次运行上述任何命令,错误仍将存在。 咱们尚未告诉 Webpack 它应该使用 Babel 和样式加载器来编译咱们的 ReactSCSS 代码。

接下来要作的是为 Babel 添加配置文件。 为此,须要建立一个名为 .babelrc 的文件,用来配置 Babel

能够直接在 webpack.config.js 文件中添加 Babel 的配置。 为此,你能够查看官方的 babel-loader 文档。 就我而言,我认为最好将 Babel 配置放在本身的文件中,这样就不会使 Webpack 配置过于复杂难读。

在根目录下建立 .babelrc

1.Linux/MacOS 命令

touch .babelrc

2.Windows 命令

echo "" > .babelrc

并在 .babelrc 中添加如下代码,这样 babel-loader 就会知道用什么来编译代码:

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

完成这些步骤后,咱们须要在项目中添加一些内容,以便咱们能够导入各类文件,如图像。 还须要添加一个插件,让咱们可使用类等等。 让咱们在类中添加类属性,基本上,它将让咱们可以使用 面向对象编程 方式来编写代码。

所以,让咱们将 webpack.config.js 更改成如下内容(我也添加了一些注释,可能会对你有所帮助):

// old
// const path = require('path');
// const HtmlWebpackPlugin = require('html-webpack-plugin');

// new
import 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: [
      {
        // 这样咱们就能够将React、ES6及以上的任何内容编译成正常的ES5语法
        test: /\.(js|jsx)$/,
        // 不但愿编译node_modules中的任何内容
        exclude: /node_modules/,
        use: ['babel-loader']
      },
      {
        test: /\.(css|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
        ]
      },
      {
        test: /\.(jpg|jpeg|png|gif|mp3|svg)$/,
        loaders: ['file-loader']
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname,'src','index.html')
    })
  ]
};

咱们须要对 package.json 文件作一个更改。咱们须要告诉咱们的脚本在 Webpack 的配置文件中,使用 import 而不是 require 语句。 不然它会给咱们一个错误,它不知道import 表示什么。

{
  "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+https://github.com/creativetimofficial/react-webpack-babel-tutorial.git"
  },
  "keywords": [
    "react",
    "webpack",
    "babel",
    "creative-tim",
    "material-design"
  ],
  "author": "Creative Tim <hello@creative-tim.com> (https://www.creative-tim.com/)",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/creativetimofficial/react-webpack-babel-tutorial/issues"
  },
  "homepage": "https://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"
  }
}

咱们还须要在 .babelrc 文件中添加 @babel/plugin-proposal-class 属性,Babel将会知道如何处理类属性。

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

如今总算配置完成了。再次运行上述任何一个命令,就能够顺利跑起来啦。

npm run webpack

图片描述

npm start

图片描述

图片描述

使用 Webpack 和 Babel 项目将 Material Design 加到咱们的新 React 项目中

正如在这篇文章的开头讲的,咱们不会讲 Material Design 样式如何写,这须要大量的工做。

相反,这里添加一个很好的产品来实现 Google 的 Material Design,其中包括Creative Tim 员工的一些小改动。 咱们将向其添加 Material Dashboard React

图片描述

首先从 github 上把项目拷贝下来:

git clone https://github.com/creativetimofficial/material-dashboard-react.git
  • Download from Github

好的,如今咱们有两个项目 - Material Dashboard React 和 咱们刚建立的项目。

图片描述

如今,咱们不能简单地将 src 文件夹从 Material Dashboard React 复制到咱们的新项目中。 这会给咱们带来不少错误, 如缺乏依赖关系的错误,找不到模块等。

所以,我建议首先将 Material Dashboard Reactpackage.json 中的依赖项添加到 package.json 中。 咱们不须要 Material Dashboard React 包中的全部依赖项,由于咱们使用 Webpack 构建了本身的服务器。 除了产品自己,咱们还添加了其余样式加载器。

因此说,咱们须要以下:

npm install --save @material-ui/core@3.1.0 @material-ui/icons@3.0.1 @types/googlemaps@3.30.11 @types/markerclustererplus@2.1.33 chartist@0.10.1 classnames@2.2.6 perfect-scrollbar@1.4.0 react-chartist@0.13.1 react-google-maps@9.4.5 react-router-dom@4.3.1 react-swipeable-views@0.12.15

咱们不会所有都讲,你能够在 npmjs.com 上找到它们的详细信息和它们本身的文档。

再一次,进入 package.json 文件并从咱们刚刚安装的安装包中删除(^)

接着拷贝 Material Dashboard React src 下的全部文件到咱们项目 src

好了,差很少作完了,咱们拷贝 Material Dashboard React 下的 src文件中全部内容到咱们项目 src 下,并覆盖 index.js 文件。可是要保留 index.html 文件。

拷贝前

拷贝前

拷贝后

拷贝后

如今须要在 index.html 中添加一些样式和字体,以下:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <link rel="stylesheet" href="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.css">
    <script src="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.js"></script>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons">
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    <title>React Tutorial</title>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.
    -->
  </body>
</html>

还有一个小问题。 当咱们刷新页面时,有一个错误 Cannot GET/dashboard。 若是咱们跳转到另外一个页面,会获得如, Cannot GET /user错误等 。 因此根本上,咱们的路由不起做用,须要在 src/index.jswebpack.config.js 中进行一些更改。

这里选择使用第一个方案,由于它很是简单易懂。

咱们在新导航方式在 index.js 更改 history,使用 createHashHistory() 替换 createBrowserHistory()

这将容许咱们刷新页面而不会出现任何其余错误,如今咱们完成了。

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(
  <Router history={hist}>
    <Switch>
      {indexRoutes.map((prop, key) => {
        return <Route path={prop.path} component={prop.component} key={key} />;
      })}
    </Switch>
  </Router>,
  document.getElementById("root")
);

原文:
https://medium.freecodecamp.o...

你的点赞是我持续分享好东西的动力,欢迎点赞!

欢迎加入前端你们庭,里面会常常分享一些技术资源。

clipboard.png

相关文章
相关标签/搜索