搭建一个React工程的方式有很多,官方也有自己的脚手架,如果你和我一样,喜欢刨根究底,从零开始自己一行一行代码创建一个React脚手架项目,那你就来对地方了。本教程是针对React新手,以及对webpack还不熟悉的用户,或者是想了解当前前端工程化方案的用户。我会在整个系列通过webpack4的配置,从生产和开发环境分别入手,包含代码压缩,大文件gz压缩,webpack4的code split,postcss等插件如何引入,css编译,如何让环境支持各种css预处理器,cssModule配置化,bundle结果分析,本地代理配置,React相关技术栈等等都有一个讲解。本系列教材由浅入深,将会从零开始一步步完善整个脚手架。

前提条件

在开始之前,请确保安装了 Node.js 的最新版本。建议使用 Node.js 最新的长期支持版本(LTS - Long Term Support)。如果你使用旧版本,你可能遇到各种问题,因为它们可能缺少 本教程用到的相关的 package 包。

执行以下命令可以查看你本机安装的node版本:
node -v && npm -v
如果你本机的node版本不是最新的,建议升级到新的node版本。node版本建议通过nvm进行管理,了解可以查看 http://nvm.sh 这里不再阐述。

通过本课程,你会学到什么?
学习完本系列教程,你将会了解(持续更新):
  1. 前端开发的框架,工程化的方式
  2. webpack4的基础配置以及常用的一些插件
  3. postcss的使用,以及常用的postcss插件
  4. 开发环境和生产环境的脚本的不同
  5. 如何让控制台输出编译结果更加高大上
  6. 大文件如何进行gz压缩
  7. 让css Module可配置化
  8. 接口转发
  9. 如何进行bundle分析
  10. 如何规范代码,如何更好地整合eslint。
  11. 如何测试React代码
1.从空文件夹开始
 
现在创建一个空的文件夹,用你的开发工具打开它。
打开终端,确保你已经进入刚刚创建的目录,接下去执行:
npm init

终端会让你输入一些信息,比如名字,版本,描述,入口文件等等。 完成后,npm会自动在你的根目录生成 package.json 文件。package.json 文件不仅仅包含项目的配置信息(比如名称、版本、许可证等元数据),还会记录项目所需要的各种模块,以及项目运行的脚本等等。

2.安装webpack4
 
本教程使用webpack来管理react工程。
执行以下命令,安装webpack

npm install --save-dev webpack

npm安装的包会存放在一个叫node_modules文件夹。如果你用的npm版本是npm 5版本,你还会发现多了package-lock.json文件。package-lock.json文件是当 node_modules 或 package.json 发生变化时自动生成的文件,它的主要功能是确定当前安装的包的依赖,以便后续重新安装的时候生成相同的依赖,而忽略项目开发过程中有些依赖已经发生的更新(翻译自官方说明)。

打开package.json,你会发现多了一个名为devDependencies的属性,通过--save-dev安装的包会记录在此属性下。后续我们还会使用--save去安装一个模块包,区别是通过--save安装的模块会记录在dependencies属性内,而不是devDependencies属性。通过字面意思,你应该也可以知道,一个是dev开发时候的依赖,一个是运行时的依赖。

新建webpack配置文件。webpack 的配置文件,是导出一个对象的 JavaScript 文件。在根目录创建build文件夹,添加一个js文件,命名为webpack.base.conf.js。
手动敲入以下代码:

        const path = require('path');
const DIST_PATH = path.resolve(__dirname, '../dist'); module.exports = {
entry: {
app: './app/index.js'
},
output: {
filename: "js/bundle.js",
path: DIST_PATH
}
};

webpack 配置是标准的 Node.js CommonJS 模块,它通过require来引入其他模块,通过module.exports导出模块,由 webpack 根据对象定义的属性进行解析。

这里定义了2个属性。当然,webpack的配置属性远远不止这2个,之后我会深入讲解更多属性的配置。回到我们定义的2个属性,entry定义了入口文件,output定义了编译后的输出。按照对这段代码的理解,它应该是告诉webpack,我这个项目入口文件是app目录下的index.js文件,你编译后,在根目录下创建dist文件夹(如果不存在),最后把编译后的文件输出到dist文件下,命名为bundle.js。

webpack4.0还增加了mode属性,用来表示不同的环境。
我们使用merge的方式来组织webpack基础配置和不同环境的配置。
先安装webpack-merge:

npm install --save-dev webpack-merge

在build文件夹中再添加一个js文件,命名为webpack.prod.conf.js,输入以下代码。

    const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf');
module.exports = merge(baseWebpackConfig, {
mode: 'production'
});

在根目录下创建app目录,然后创建index.js文件。

    var element =document.getElementById('root');
element.innerHTML = 'hello, world!';

在根目录创建一个public文件夹,然后新建一个index.html文件。

    <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>从零开始搭建react工程</title>
</head>
<body>
<div id="root"></div>
<script src="../dist/js/bundle.js"></script>
</body>
</html>

你现在的文件路径应该看起来是这样:(显然我们引用的bundle.js并不存在)

      |- /app
|- index.js
|- /node_modules
|- /public
|- index.html
|- /build
|- webpack.base.conf.js
|- webpack.prod.conf.js
|- package.json
|- package-lock.json

接下去我们要通过执行webpack命令,来编译我们的代码,生成bundle.js。4.0版本之后的webpack,已经将webpack命令工具迁移到webpack-cli模块了。你需要安装webpack-cli。

npm install --save-dev webpack-cli

安装完成后,执行下面脚本进行编译:

webpack --config build/webpack.prod.conf.js

编译完成后,刷新根目录,可以看到已经生成dist文件夹和bundle.js文件。
用浏览器打开html文件,你会看到hello webpack。我们成功通过webpack编译了js文件,并且没有出现问题。
webpack --config build/webpack.prod.conf.js命令,我们可以通过npm scripts管理起来。
在package.json文件,我们为scripts属性配置一个build命令,其值为:webpack --config build/webpack.prod.conf.js,以下是scripts的相关代码:

    "scripts": {
"build": "webpack --config build/webpack.prod.conf.js",
"test": "echo \"Error: no test specified\" && exit 1"
},

然后在命令行输入:

npm run build

我们可以看到,webpack重新进行了编译,这和执行
webpack --config build/webpack.prod.conf.js 是一样的效果。

3.安装react
 
在终端输入以下命令:
npm install --save react react-dom

安装成功后,我们在项目使用react,我们直接修改app目录下的index.js的代码,我们用react来插入这句hello world!

    import React from "react";
import ReactDom from "react-dom"; ReactDom.render(
<h1>hello, world!</h1>,
document.getElementById("root")
);

好了,我们再编译试试看。

npm run build

失败了?对不对!首先,我告诉你这段代码没有任何问题,你需要思考下,它为什么会编译失败。下一小节,我们一起来了解下原因。

4.整合babel 7.0
 
为什么会失败?因为webpack只识别JavaScript文件,而且只能编译es5版本的JavaScript语法。实际上,我们使用ES2015,以及jsx的语法糖,webpack它根本不认识啊。怎么办?webpack 可以使用 loader 来预处理文件。它不仅仅可以处理JavaScript本身,还允许你打包任何的静态资源。
其中,babel-loader,就是这样一个预处理插件,它加载 ES2015+ 代码,然后使用 Babel 转译为 ES5。我们来了解下如何在webpack配置babel-loader。
首先安装babel相关的模块:
npm install --save-dev babel-loader @babel/preset-react @babel/preset-env @babel/core

除了babel-loader,我们还安装了好多的包,其中@babel/core是babel的核心模块,@babel/preset-env是转译ES2015+的语法,@babel/preset-react是转译react的JSX以及FLOW。了解详情可以移步 babel官方。
第二步,你需要在根目录建立一个.babelrc的文件,配置相关的presets:

    {
"presets": [
[
"@babel/preset-env",
{
"targets": {
"browsers": [
"> 1%",
"last 5 versions",
"ie >= 8"
]
}
}
],
"@babel/preset-react"
]
}

更多关于babel的配置可以看下官方http://babeljs.io/docs/en的说明,这里不再阐述。

第三步,修改webpack.base.conf.js文件。

    const path = require('path');
const APP_PATH = path.resolve(__dirname, '../app');
const DIST_PATH = path.resolve(__dirname, '../dist');
module.exports = {
entry: {
app: './app/index.js'
},
output: {
filename: 'js/bundle.js',
path: DIST_PATH
},
module: {
rules: [
{
test: /\.js?$/,
use: "babel-loader",
include: APP_PATH
}
]
}
};

在 webpack 配置中定义 loader 时,要定义在 module.rules 中。其中,test和use属性是必须的。include属性,定义了rules执行的范围。这告诉 webpack 编译器如下信息:
嘿,webpack 编译器,你在编译文件过程中,如果这个是在app目录下的js文件,在你对它打包之前,先使用 babel-loader 转换一下。
重新执行本地编译

npm run build

这次不再报错,编译成功。
好了,再次打开public目录的index.html,页面成功显示了hello world。
可能,你还有一些疑惑,html文件如何也同步到dist目录?bundle.js文件修改了,万一被浏览器缓存了怎么办?如何通过script标签把打包生成的js自动添加到html?react和业务代码如何分开打包?如何实现开发环境的热更新?

下一章,我将针对这些问题,会一一进行讲解,并且持续优化我们的工程。

【webpack系列】从零搭建 webpack4+react 脚手架(一)的更多相关文章

  1. 【webpack系列】从零搭建 webpack4+react 脚手架(四)

    经过三个章节的学习,你已经学会搭建了一个基于webpack4的react脚手架.如果要更改配置,比如,你希望把编译后的js文件和css文件等单独放dist下的static目录下,你想想,是不是有点麻烦 ...

  2. 【webpack系列】从零搭建 webpack4+react 脚手架(三)

    本章节,我们对如何在脚手架中引入CSS,如何压缩CSS,如何使用CSS Modules,如何使用less,如何使用postcss等问题进行展开学习. 1 支持css (1)在app目录,新建一个css ...

  3. 【webpack系列】从零搭建 webpack4+react 脚手架(二)

    html文件如何也同步到dist目录?bundle.js文件修改了,万一被浏览器缓存了怎么办?如何为导出的文件加md5?如何把js引用自动添加到html?非业务代码和业务代码如何分开打包?如何搭建开发 ...

  4. 【webpack系列】从零搭建 webpack4+react 脚手架(五)

    本章节,我们一起来探讨以下问题:如何对编译后的文件进行gzip压缩,如何让开发环境的控制台输出更加高逼格,如何更好的对编译后的文件进行bundle分析等. 1 gzip压缩 如果你想节省带宽提高网站速 ...

  5. 从零搭建Spring Boot脚手架(1):开篇以及技术选型

    1. 前言 目前Spring Boot已经成为主流的Java Web开发框架,熟练掌握Spring Boot并能够根据业务来定制Spring Boot成为一个Java开发者的必备技巧,但是总是零零碎碎 ...

  6. 初探webpack之从零搭建Vue开发环境

    初探webpack之搭建Vue开发环境 平时我们可以用vue-cli很方便地搭建Vue的开发环境,vue-cli确实是个好东西,让我们不需要关心webpack等一些繁杂的配置,然后直接开始写业务代码, ...

  7. 从零搭建Spring Boot脚手架(2):增加通用的功能

    1. 前言 今天开始搭建我们的kono Spring Boot脚手架,首先会集成Spring MVC并进行定制化以满足日常开发的需要,我们先做一些刚性的需求定制,后续再补充细节.如果你看了本文有什么问 ...

  8. 从零搭建Spring Boot脚手架(3):集成mybatis

    1. 前言 今天继续搭建我们的kono Spring Boot脚手架,上一文集成了一些基础的功能,比如统一返回体.统一异常处理.快速类型转换.参数校验等常用必备功能,并编写了一些单元测试进行验证,今天 ...

  9. 从零搭建Spring Boot脚手架(4):手写Mybatis通用Mapper

    1. 前言 今天继续搭建我们的kono Spring Boot脚手架,上一文把国内最流行的ORM框架Mybatis也集成了进去.但是很多时候我们希望有一些开箱即用的通用Mapper来简化我们的开发.我 ...

随机推荐

  1. ICPC China Nanchang National Invitational -- D. Match Stick Game(dp)

    题目链接:https://nanti.jisuanke.com/t/38223 题意:有一堆火柴构成了一个加减法式子,你可以把火柴重新组合,要求数字个数和原来一样多,每个数字的位数和对应原数字位数一样 ...

  2. windows下网络编程UDP

    转载 C++ UDP客户端服务器Socket编程 UDPServer.cpp #include<winsock2.h>#include<stdio.h>#include< ...

  3. window.location.href 传参中文乱码问题!!!

    不是所有地方都会用Ajax  当你使用window.location.href 来传中文参数的时候 如何避免乱码问题 js 是这样写的    下面代码中  方式 封装编码  参数 username  ...

  4. An SDN-NFV Platform for Personal Cloud Services

    文章名称:An SDN-NFV Platform for Personal Cloud Services 发表时间:2017 期刊来源:IEEE Transactions on Network and ...

  5. 微信小程序版本自动更新弹窗提示

    代码如下: onLaunch () { if (wx.canIUse('getUpdateManager')) { const updateManager = wx.getUpdateManager( ...

  6. ioctl函数

    一.函数原型 #include <unistd.h> int ioctl(int fd, int request, .../* void *arg */); 二.和网络相关的请求(requ ...

  7. git bash 支持中文

      1. 编辑etc\gitconfig文件,在文件末尾增加以下内容: [gui] encoding = utf-8 #代码库统一使用utf-8 pathnameencoding = utf-8 #支 ...

  8. rem是怎么计算的(转载)

    「rem」是指根元素(root element,html)的字体大小,从遥远的 IE6 到版本到 Chrome 他们都约好了,根元素默认的 font-size 都是 16px. rem是通过根元素进行 ...

  9. 内网环境上部署k8s+docker集群:集群ftp的yum源配置

    接触docker已经有一年了,想把做的时候的一些知识分享给大家. 因为公司机房是内网环境无法连接外网,所以这里所有的部署都是基于内网环境进行的. 首先,需要通过ftp服务制作本地的yum源,可以从ht ...

  10. UTF-8字符C2A0引起的问题

    今天遇到一个问题: 网页上的一段文字中有几个空格,把这段文字当作文件名称保存为一个windows系统下的文件后,文件名中本来是空格的地方变成了问号,另外一个C#程序打开这个文件,也提示找不到文件. 初 ...