搭建react项目(上)

前言

最近因为公司的项目需求,所以需要react项目搭建这方面的知识,需要添加和修改webpack中的配置。以前的话react项目搭建都是直接使用官方脚手架进行搭建的create-react-app react-project,但是由于其中的webpack配置都是在node_modules中,我们想要更改配置可以使用eject命令弹出配置,或者使用react-app-rewired来进行配置。这次呢主要是想教大家如何去搭建一个react项目,让我们更加了解react是怎么在本地跑起来的,是如何配置解析sass和js的,这样我们就可以随意配置自己的项目。

一个react项目需要什么

首先我们要考虑下一个react项目中我们需要什么,并不是按照下面的顺序来讲的哦~

  1. 我们需要react(这当然是最基本的啦)

  2. 要让js代码在本地跑起来

  3. 我们会使用到es6等语法,但由于一些浏览器还不支持es6的全部语法,那么我们就需要一个编译器让es6变成es5在浏览器上去运行。

  4. 性能方面的优化,比如代码优化。

  5. 一些最基本的插件支持。

react项目基本配置

第一件最重要最重要的事,就是在先创建一个名字叫app的文件夹,当然叫啥随便你啦。然后使用npm init -y这个命令会给你创建一个最基本的webpack.json文件。

第二就是你在app文件夹下面创建一个src文件夹(后面所有没有明确指出的,都是指在app文件夹下),然后在src中创建一个index.js, 写上以下代码。

    console.log('hello world');
    console.log('hello react-app');

然后我们在终端中使用 npm add webpack webpack webpack-cli webpack-dev-server babel-loader --D

webpack:一个打包工具,可以在其中配置很多的插件。

webpack-cli:我们可以使用webpack的命令。

webpack-dev-server:创建一个用于开发环境的本地服务器,不需要使用node开创建一个服务器。

babel-loader:将es6语法转换成es5。

@babel/core:babel的核心编译器,允许我们使用babel-loader的依赖项,没有这玩意你有babel-loader也没有。

我们打开package.json文件会看到以下内容

{
  "name": "app",  
  "version": "1.0.0",  
  "description": "",  
  "main": "index.js",  
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },  
  "keywords": [],  
  "author": "",  
  "license": "ISC",  
  "dependencies": {},  
  "devDependencies": {
    "@babel/core": "^7.4.3",  
    "babel-loader": "^8.0.5",  
    "webpack": "^4.29.6",  
    "webpack-cli": "^3.3.0",  
    "webpack-dev-server": "^3.2.1"
  }
}

我在这找几个最重要的讲解下:

main:表示的是入口文件。

dependencies:生产环境的依赖

devDependencies:开发环境的依赖

创建一个config文件夹,在其中创建webpack.base.config.js表示这个文件里的是webpack最基本的配置,然后写上以下代码

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

rules:里面放置的是各种loader, loader就是将在项目中能够识别该类型然后实现对应的转换,比如将sass转换成css, 将es6的js转换成浏览器能够识别的es5.

test:告诉webpack对哪种类型的文件进行转换,可以是正则。

exclude:不包含该文件下的文件,可以是正则。

use:使用的是什么转换器,可以是字符串和对象的形式。

entry:这里没有写,默认是'src/index.js'。这个指的是入口文件,指我们一个项目首先从哪里开始打包,然后跟链式操作一样,从该文件找到另一个文件,在从另一个找到另一个,以此类推。这里可以是一个入口文件,也可是多个入口文件.

output:告诉webpack我打包好后,我应该输出到哪个文件中,默认是'dist'文件夹中。

按照上面的配置基本上我们是配置好了,我们开始运行下,让本地服务器跑起来运行这个JS。$ node_modules/.bin/webpack-dev-server --mode development --config config/webpack.base.config.js --open --hot --history-api-fallback,这个命令稍后在讲解。

你将会看到跟下面这张图一样。

为什么会这样呢,因为没有html文件,只有JS文件,人家显示啥啊。

我们接着创建public文件夹在其中创建index.html好显示给人家看。

<!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>my app</title>
</head>
<body>
  <div id="root"></div>
</body>
</html>

接着我们要改webpack.base.config.js文件,因为我们添加了一个index.html文件,但是webpack不知道如何找到这个文件所以我们就要改配置啦。我们在去下包啦npm add html-webpack-plugin --D

html-webpack-plugin:使用一个模版html文件,按需加载css或者JS插入到模板html文件中。

webpack.base.config.js文件中的配置更改为

var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  module: {
    rules: [{
      test: /\.js$/,  
      exclude: /node_modules/,  
      use: {
        loader: 'babel-loader'
      }
    }]
  },  
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html'
    })
  ]
};

plugins:指的是webpack应用什么插件,数组的形式,你想用啥插件就用啥插件, 通过new的形式创建一个实例来使用。

template:指的是哪个模板文件。

然后在运行如下命令node_modules/.bin/webpack-dev-server --mode development --config config/webpack.base.config.js --open --hot --history-api-fallback

我们可以看到我们的console打印出来了,我们可以在index.js中接着打console或者添加一些别的东西,我们会看到my app那个页面会自动刷新,这就是热重载功能,我们在html文件中修改后页面却不会自动更新,需要手动进行刷新。

接下来我们就要使用react了,让这个项目可以使用react.使用npm add react react-dom --save命令,下载react项目所需要的react和react-dom。修改src/index.js文件

import React,   {
    Component
} from 'react';
import ReactDOM from 'react-dom';

const App = ()=>{
    return (
        <div>
            创建一个react-app成功啦
        </div>
    )
}

ReactDOM.render(<App/>,   document.getElementById('root'));

接着运行该命令node_modules/.bin/webpack-dev-server --mode development --config config/webpack.base.config.js --open --hot --history-api-fallback,会看到如下图片

为什么会报错呢,这里的意思好像是识别不了这个div, 为什么识别不了呢?我们好像还没有下载转换react的插件,因为react语法在浏览器中不能够被识别的。

知道问题就好解决了,我们去下载react对应的转换插件npm add @babel/preset-env @babel/preset-react -D

我们先创建一个 .babelrc 文件, 这里的babelrc是babel的配置文件我们只需要在这里配置好对应的转换。项目在运行的时候 webpack.base.config.js 中的"babel-loader"就会去查找balbel配置文件,如果找到就会应用那个文件,如果没有则采用默认配置文件。在其中写入

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

@babel/preset-env:允许我们使用最新的js

@babel/preset-react:允许我们使用react语法

再次运行node_modules/.bin/webpack-dev-server --mode development --config config/webpack.base.config.js --open --hot --history-api-fallback

我们能看到这个react项目运行成功了,我在这里呢只配置了最基本的功能,让这个项目能够在本地跑起来。

然后我们还需要让项目能够支持sass,使用命令yarn add sass-loader node-sass css-loader style-loader --dev.
接着去修改webpack.base.config.js中的配置.

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

module.exports = {
    module: {
        rules: [
            {
                test: /.js$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader"
                }
            },
            {
                test: /\.scss$|\.sass$/,
                use: ["style-loader", "css-loader", "sass-loader"]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./public/index.html"
        })
    ]
};

use: ["style-loader", "css-loader", "sass-loader"]:这里要提一下,这个非常重要哦,这里是从右到左的,找到对应的文件后先将文件转化为sass,然后在转换为css,接着在使用style-loader转换成文件的形式注入到index.html中。

我们现在讲解下node_modules/.bin/webpack-dev-server --mode development --config config/webpack.base.config.js --open --hot --history-api-fallback

我们这里可以拆开来分析:

node_modules/.bin/webpack-dev-server:这里指的是通过命令的形式去查找到webpack-dev-server然后运行起来这个小型的express服务器,让项目能够在本地跑起来,当然也可以自己去写的啦。

--mode development:告诉webpack是在开发模式下打开,当然你不写development也可以,可选的值:"development", "production", "none",当然你也可以随便写,这肯定会报错的。

--config config/webpack.base.config.js:这个最简单了,告诉webpack我的配置在哪里,你去那里找。

--open:编译好后,打开浏览器。

--hot:这个是让webpack监听文件进行热更新,然而不写也是热更新。

--history-api-fallback:就是你输入的页面路径是错误的时候也会跳转到index.html,但是仅限于一级路径,二级就炸了。

讲到这里,本地上运行基本没啥问题,现在我们要考虑下如何让文件打包。

我们先修改webpack.json文件,先添加快捷运行项目的命令,文件中应该有"scripts"字段,如果没有可以手动添加进去。

"scripts": {
    "start": "webpack-dev-server --mode development --config config/webpack.base.config.js --open --hot --history-api-fallback",
    "prebuild": "webpack --mode production --config config/webpack.prod.config.js",
    "build": "node server"
  }

我们现在只需要运行npm run start命令就可以把项目在本地跑起来了,不需要在打那一大串的命令了。

现在我们要加入生产环境的配置了,先使用命令下载需要的包yarn add webpack-merge --dev,然后修改config/webpack.base.config.js文件

const HtmlWebpackPlugin = require("html-webpack-plugin");
const merge = require("webpack-merge");

module.exports = () => {
    return merge([
        {
            module: {
                rules: [
                    {
                        test: /.js$/,
                        exclude: /node_modules/,
                        use: {
                            loader: "babel-loader"
                        }
                    }
                ]
            },
            plugins: [
                new HtmlWebpackPlugin({
                    template: "./public/index.html"
                })
            ]
        }
    ]);
};

html-webpack-plugin:能够让webpack配置可以和另一个配置进行合并。

接着我们创建个文件/config/webpack.prod.config.js.

const merge = require("webpack-merge");

//plugins
const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");

const baseConfig = require("./webpack.base.config");

const prodConfig = () => {
    return merge([
        {
            optimization: {
                runtimeChunk: "single",
                splitChunks: {
                    cacheGroups: {
                        vendor: {
                            test: /[\\/]node_modules[\\/]/,
                            name: "vendors",
                            chunks: "all"
                        }
                    }
                },
                minimizer: [new UglifyJsPlugin()]
            },
            plugins: [new OptimizeCssAssetsPlugin()]
        }
    ]);
};

module.exports = () => {
    return merge(baseConfig(), prodConfig());
};

optimization.splitChunks:会获取所有公共的代码把他们打包成一个vendor.bundle.js用不用就看自己的项目是否需要,因为打包了的话会造成首页加载非常的慢,因为他不需要的代码也在首页加载了,如果不需要的话,首页会变快,但是在加载各个页面的时候需要去加载文件。

uglifyjs-webpack-plugin: [new UglifyJsPlugin()]:优化JS代码。

optimize-css-assets-webpack-plugin:优化Css代码。

这里生产环境的配置也更改的差不多了,我们好像忘记了一个问题,因为我们在项目中有可能使用到图片以及别的格式文件,那我们怎么办?

我们先创建个static/img文件夹,在其中放入几张图片,你在引入该图片,会发现会报错。

所以我们先使用命令yarn add copy-webpack-plugin --dev,然后在webpack.base.config.js中进行修改.

const HtmlWebpackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");

module.exports = {
    module: {
        rules: [
            {
                test: /.js$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader"
                }
            },
            {
                test: /\.scss$|\.sass$/,
                use: ["style-loader", "css-loader", "sass-loader"]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./public/index.html"
        }),
        new CopyWebpackPlugin([{ from: "src/static" }])
    ]
};

copy-webpack-plugin:顾名思义就是复制文件,在plugins中使用,from表示的是从哪里复制,默认是复制到dist文件夹中的。

Share

You may also like...

发表评论

电子邮件地址不会被公开。 必填项已用*标注