如何使用Webpack 4从零开始创建React应用

For the past three weeks, I have been trying to create a React app from scratch to understand the set-up with Webpack. My aim was to set up a simple configuration which can then be grown upon. It’s been a struggle to understand Webpack. But thanks to this tutorial by Valentino Gagliardi, I’m much enlightened.

在过去的三个星期中,我一直在尝试从头开始创建一个React应用程序,以了解Webpack的设置。 我的目标是建立一个简单的配置,然后可以对其进行扩展。 了解Webpack一直很艰辛。 但多亏了Valentino Gagliardi撰写的教程 我才获得了很多启发。

What I’m planning to do is to make a search functionality with some fake JSON data (or real). In this blog post, I will go through the set up of my project. In the next one, I am planning to show how to set up testing. I would also like to add a server to this using Node.js, but not sure if the scope of my project would need that.

我打算做的是使用一些伪造的JSON数据(或真实数据)进行搜索。 在此博客文章中,我将完成我的项目的设置。 在下一个中,我打算展示如何设置测试。 我还想使用Node.js向其添加服务器,但是不确定我的项目范围是否需要该服务器。

(Note: I have provided my Webpack setup at the end of this blog post)

( 注意 :我在此博文末尾提供了Webpack设置)

Without further ado, let’s get on with the set up!

事不宜迟,让我们继续进行设置!

Make a new project and cd into it:

制作一个新项目 ,并将其放入CD

mkdir react_searchcd react_search

Create a package.json file:

创建一个package.json文件:

npm init

If you want to skip all the questions, add the -y flag:

如果要跳过所有问题,请添加-y标志:

npm init -y

We need to install webpack as a dev dependency and webpack-cli so that you can use webpack in the command line:

我们需要将webpack安装为dev依赖项和webpack-cli,以便可以在命令行中使用webpack:

npm i webpack webpack-cli -D
  • i: install

    我:安装
  • -D: — save-dev

    -D:—保存开发

Create a src folder with index.js and place the following code as an example:

使用index.js创建一个src文件夹 ,并将以下代码作为示例:

console.log("hello");

Now add the following scripts to your package.json (in bold):

现在,将以下脚本添加到package.json中(粗体):

{
  "name": "react_search",
  "version": "1.0.0",
  "description": "Search app using React",
  "main": "index.js",
  
"scripts": {
    "start": "webpack --mode development",
    "build": "webpack --mode production"
  
},  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.0.1",
    "webpack-cli": "^2.0.10"
  }
}

Webpack 4 now has two modes, development and production where code is minimised in the latter.

Webpack 4现在具有两种模式,即开发生产 ,其中将后者的代码减至最少。

See it for yourself by running:

通过运行以下命令自己查看:

npm run start

This will create a dist folder with main.js file inside (containing your src code).

这将创建一个dist文件夹,其中包含main.js文件(包含您的src代码)。

If you now run:

如果现在运行:

npm run build

The following output is now like this:

现在的输出如下所示:

设置React和Babel (Setting Up React and Babel)

To work with React, we need to install it along with Babel. This will transpile the code from ES6 to ES5, as not all browsers support ES6 yet (for example Internet Explorer).

要使用React,我们需要将其与Babel一起安装。 由于并非所有浏览器都支持ES6(例如Internet Explorer),因此会将代码从ES6转换为ES5。

Install react and react-dom as a dependency

安装reactreact-dom作为依赖项

npm i react react-dom -S
  • -S: — save

    -S:—保存

Then install babel-core, babel-loader, babel-preset-env and babel-preset-react as a dev dependency:

然后安装babel-corebabel-loaderbabel-preset-envbabel-preset-react作为dev依赖项:

npm i babel-core babel-loader babel-preset-env babel-preset-react -D
  • babel-core: Transforms your ES6 code into ES5

    babel-core :将您的ES6代码转换为ES5

  • babel-loader: Webpack helper to transform your JavaScript dependencies (for example, when you import your components into other components) with Babel

    babel-loader :Webpack助手,可通过Babel转换您JavaScript依赖关系(例如,当您将组件导入其他组件时)

  • babel-preset-env: Determines which transformations/plugins to use and polyfills (provide modern functionality on older browsers that do not natively support it) based on the browser matrix you want to support

    babel-preset-env :基于要支持的浏览器矩阵,确定要使用的转换/插件和polyfill(在本机不支持它的较旧浏览器中提供现代功能)

  • babel-preset-react: Babel preset for all React plugins, for example turning JSX into functions

    babel-preset-react :所有React插件的Babel预设,例如将JSX转换为功能

We need to create a webpack.config.js file to state the rules for our babel-loader.

我们需要创建一个webpack.config.js文件来声明babel-loader的规则。

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      }
    ]
  }
};

We then need to make a separate file called .babelrc to provide the options for babel-loader. You can include it in the webpack.config.js file, but I have seen that most projects have this separated. This results in clearer readability, and it can be used by other tools unrelated to webpack. When you state that you’re using babel-loader in your webpack config, it will look for .babelrc file if there is one.

然后,我们需要制作一个名为.babelrc的单独文件,以提供babel-loader的选项。 您可以将其包含在webpack.config.js文件中,但是我已经看到大多数项目对此进行了分隔。 这样可以提高可读性,并且可以与Webpack无关的其他工具使用它。 当您声明在Webpack配置中使用babel-loader时,它将查找.babelrc文件(如果有)。

{
  "presets": ["env", "react"]
}

Next, change your index.js file to render a component:

接下来,更改您的index.js文件以呈现组件:

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

const Index = () => {
  return <div>Hello React!</div>;
};

ReactDOM.render(<Index />, document.getElementById("index"));

We will also need to create an index.html file in the src folder where we can add our section element with id index. This is where we render our main react component:

我们还需要在src文件夹中创建index.html文件,在其中可以添加ID为index section元素。 这是我们渲染主要react组件的地方:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>React and Webpack4</title>
</head>
<body>
  <section id="index"></section>
</body>
</html>

Now we need to install html-webpack-plugin and use this in our webpack config file. This plugin generates an HTML file with <script> injected, writes this to dist/index.html, and minifies the file.

现在我们需要安装html-webpack-plugin并在我们的webpack配置文件中使用它。 该插件生成一个注入了<script>HTML文件,将其写入dist / index .html,并缩小该文件。

Install html-webpack-plugin as a dev dependency:

html-webpack-plugin安装为dev依赖项:

npm i html-webpack-plugin -D

Update the webpack config like so:

像这样更新webpack配置:

const HtmlWebPackPlugin = require("html-webpack-plugin");

const htmlPlugin = new HtmlWebPackPlugin({
  template: "./src/index.html",
  filename: "./index.html"
});

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      }
    ]
  },
  plugins: [htmlPlugin]
};

You can also input the plugin like this:

您也可以这样输入插件:

plugins: [
    new HtmlWebPackPlugin({
    template: "./src/index.html",
    filename: "./index.html"
  });
]

But I prefer to extract this into a variable so I can see the list of plugins I am using.

但是我更喜欢将其提取到变量中,这样我就可以看到我正在使用的插件列表。

The value I am giving the template key is where I am looking for my HTML file. The filename value is the name of the minified HTML that will be generated in the dist folder.

我给template密钥的值是我要查找HTML文件的位置。 文件名值是将在dist文件夹中生成的缩小HTML的名称。

If you now run npm run start you should see index.html being generated in the dist folder.

如果现在运行npm run start ,则应该在dist文件夹中看到正在生成index.html

Run open dist/index.html and you should see “Hello React” in your browser.

运行open dist/index.html ,您应该在浏览器中看到“ Hello React”。

设置webpack-dev-server (Setting up webpack-dev-server)

It is a bit tedious to keep running this command every time you want to see your changes in the browser. To have webpack “watch” our changes and thus refresh whenever we have made changes to any of our components, we can use webpack-dev-server module.

每次要在浏览器中查看更改时,保持运行此命令有点麻烦。 为了使webpack“观察”我们的更改并因此在我们对任何组件进行更改时刷新,我们可以使用webpack-dev-server模块。

Go ahead and install this as a dev dependency

继续并将其安装为开发依赖项

npm i webpack-dev-server -D

Then change your package.json start scripts like so (in bold):

然后像这样(以粗体显示)更改您的package.json启动脚本:

{
  "name": "react_search",
  "version": "1.0.0",
  "description": "Search app using React",
  "main": "index.js",
  "scripts": {
  
  "start": "webpack-dev-server --mode development --open",    "build": "webpack --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^16.2.0",
    "react-dom": "^16.2.0"
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.4",
    "babel-preset-env": "^1.6.1",
    "babel-preset-react": "^6.24.1",
    "html-webpack-plugin": "^3.0.6",
    "webpack": "^4.1.1",
    "webpack-cli": "^2.0.10",
    "webpack-dev-server": "^3.1.0"
  }
}

If you now run npm run start you should see localhost:8080 open up in your default browser — that’s what the —-open flag is for. Now everytime you make changes, it will refresh the page.

如果现在运行npm run start ,则应该在默认浏览器中看到localhost:8080打开-这就是—-open标志的作用。 现在,每次进行更改时,它将刷新页面。

You can also add a --hot flag to your npm start script which will allow you to only reload the component that you’ve changed instead of doing a full page reload. This is Hot Module Replacement.

您还可以在npm start脚本中添加--hot标志,这将允许您仅重新加载已更改的组件,而不必重新加载整个页面。 这是热模块更换

设置CSS (Setting up CSS)

The last part involves setting up our CSS. As we will be importing CSS files into our React components, we need css-loader module to resolve them. Once that’s resolved, we also need a style-loader to inject this into our DOM — adding a <style> tag into the <head> element of our HTML.

最后一部分涉及设置CSS。 当我们将CSS文件导入到React组件中时,我们需要css-loader模块来解决它们。 解决之后,我们还需要一个样式加载器将其注入到我们的DOM中—在HTML的<head>元素中添加一个<style>标记。

Go ahead and install both of these modules as a dev dependency:

继续并安装这两个模块作为dev依赖项:

npm i css-loader style-loader -D

We then need to update our webpack.config.js file like so:

然后,我们需要像这样更新我们的webpack.config.js文件:

const HtmlWebPackPlugin = require("html-webpack-plugin");

const htmlWebpackPlugin = new HtmlWebPackPlugin({
  template: "./src/index.html",
  filename: "./index.html"
});

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"]
      }
    ]
  },
  plugins: [htmlWebpackPlugin]
};

Note that the order of adding these loaders is important. First, we need to resolve the CSS files before adding them to the DOM with the style-loader. By default, webpack uses the loaders from the right (last element in the array) to the left (first element in the array).

请注意,添加这些装载程序的顺序很重要。 首先,我们需要先解析CSS文件,然后再使用样式加载器将它们添加到DOM中。 默认情况下,webpack使用从右侧(数组中的最后一个元素)到左侧(数组中的第一个元素)的加载程序。

使CSS模块化 (Making CSS modular)

We can also make CSS modular using webpack. This means class name will be scoped locally and specific to only the component in question.

我们还可以使用webpack使CSS模块化。 这意味着类名称将在本地范围内并且仅特定于所讨论的组件。

To do this, we can provide some options to css-loader:

为此,我们可以为css-loader提供一些选项:

const HtmlWebPackPlugin = require("html-webpack-plugin");

const htmlWebpackPlugin = new HtmlWebPackPlugin({
  template: "./src/index.html",
  filename: "./index.html"
});

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      {
        test: /\.css$/,
        use: [
          {
            loader: "style-loader"
          },
          {
            loader: "css-loader",
            options: {
              modules: true,
              importLoaders: 1,
              localIdentName: "[name]_[local]_[hash:base64]",
              sourceMap: true,
              minimize: true
            }
          }
        ]
      }
    ]
  },
  plugins: [htmlWebpackPlugin]
};

As we need to give options, each loader is now an object with a key-value pair. To enable CSS modules, we need to set module option for css-loader to be true. The importLoaders option configures how many loaders before css-loader should be applied. For example, sass-loader would have to come before css-loader.

由于需要提供选项,因此每个加载器现在都是带有键值对的对象。 要启用CSS模块,我们需要将css-loader的module选项设置为trueimportLoaders选项配置在应用css-loader之前应应用多少个加载器。 例如,sass-loader必须先于css-loader。

The localIdentName allows you to configure the generated identification.

localIdentName允许您配置生成的标识。

  • [name] will take the name of your component

    [名称]将使用您的组件的名称

  • [local] is the name of your class/id

    [local]是您的班级/ ID的名称

  • [hash:base64] is the randomly generated hash which will be unique in every component’s CSS

    [hash:base64]是随机生成的哈希,在每个组件CSS中都是唯一的

To make this a bit more visual, I’ll give you an example. Say I have a component named Form and I have a button with a CSS class primaryButton. I also have another component called Search and a button in it with a CSS class primaryButton. However, both of these classes have different CSS:

为了更加直观,我将举一个例子。 假设我有一个名为Form的组件,并且有一个带有CSS类primaryButton的按钮。 我还具有另一个名为Search组件,以及一个带有CSS类primaryButton的按钮。 但是,这两个类都有不同CSS:

Form button.primaryButton {
  background-color: green;
}
Search button.primaryButton {
  background-color: blue;
}

When webpack bundles your application, depending on which CSS comes latest, both of your buttons could have the color green or blue instead of Form having green and Search having blue.

当webpack捆绑您的应用程序时,这取决于最新CSS,这两个按钮都可能具有绿色或蓝色,而不是表单具有绿色和搜索具有蓝色。

This is where the localIdentName comes into place. With this, once your application is bundled, your buttons will have a unique class name!

这是localIdentName的位置。 这样,将您的应用程序捆绑后,您的按钮将具有唯一的类名称!

As you can see, the button class name in the Form component is different to the one in the Search component — their naming starts with the name of the component, class name, and unique hash code.

如您所见,Form组件中的按钮类名称与Search组件中的按钮类名称不同-它们的命名始于组件名称,类名称和唯一的哈希码。

So with this, you won’t have to worry about whether you have given the same class name throughout your whole application — you only have to worry about whether you have used it in the same component.

因此,您不必担心在整个应用程序中是否给定了相同的类名-您只需要担心是否在同一组件中使用过它。

This concludes the first part of setting a React app from scratch. In the next blog post, I aim to explain how to set up tests for TDD and how to write them.

到此结束从头开始设置React应用程序的第一部分。 在下一篇博客文章中,我旨在解释如何为TDD设置测试以及如何编写测试。

Please let me know if something is unclear and I’ll explain the best as I can. I value and welcome constructive feedback as this helps me to improve :)

如果有不清楚的地方,请告诉我,我会尽力向您解释。 我重视并欢迎建设性的反馈意见,因为这有助于我改善:)

Hope this helps!

希望这可以帮助!

编辑 (EDIT)

导入CSS (Importing CSS)

I’ve had a few comments asking me how they can render CSS which I didn’t touch on previously. What you need to do is import the CSS file in your React component. For example, say you have a Search component and this is your tree directory:

我有一些评论询问我如何渲染CSS,这是我之前没有提到的。 您需要做的是将CSS文件导入到React组件中。 例如,假设您有一个Search组件,这是您的树目录:

You will need to import your CSS file in your Search component like so:

您将需要将CSS文件导入Search组件中,如下所示:

import style from "./Search.css"

You can then apply different CSS class styles such as:

然后,您可以应用不同CSS类样式,例如:

const Search = () => {
  return <div className={style.
nameOfYourCSSClass}>
           Hello Search Component :)
         </div>
}

You don’t have to call it style but what I found is that most people have given it this name in their projects.

您不必称其为样式,但是我发现大多数人在他们的项目中都给它起了这个名字。

我的Webpack样板 (My Webpack boilerplate)

For anyone who wants a quick clone of this Webpack setup, I have this on my GitHub. I’ve also included a more succinct guide in the README.

对于任何想要快速克隆此Webpack设置的人,我都在GitHub上 。 我还在自述文件中包含了更简洁的指南。

输入和输出点 (Entry and output points)

Webpack 4 by default has a default entry point of index.js in your src folder. If you would like to point to a different file, you can do so by specifying an entry point in your webpack config file:

默认情况下,Webpack 4在src文件夹中具有index.js的默认入口点。 如果要指向其他文件,可以通过在webpack配置文件中指定一个入口点来实现:

e.g.

例如

module.exports = {
  
entry: "./src/app.js",  module: {
   ...
  }
}

You can also specify output file like so:

您也可以这样指定输出文件:

const path = require('path')
module.exports = {
  entry: "./src/app.js",
  
output: {
    path: path.resolve(‘dist’),
    filename: ‘bundled.js’
  },
  
module: {
    ...
  }
}

Thanks to Gudu Kassa for pointing this out!

感谢Gudu Kassa指出了这一点!

If you have found this helpful please share it on social media :)

如果您发现这有帮助,请在社交媒体上分享:)

www.pinglinh.com

www.pinglinh.com

Follow me on Twitter | Check out my LinkedIn | See my GitHub

Twitter上关注我| 查看我的领英 | 查看我的GitHub

翻译自: https://www.freecodecamp.org/news/part-1-react-app-from-scratch-using-webpack-4-562b1d231e75/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值