likes
comments
collection
share

”高级女秘书“ —— webpack 创建一个 React 应用

作者站长头像
站长
· 阅读数 11

webpack

webpack 简介

有说 webpack 是打包机,也有人说它是加工厂,我总感觉它像一个高级的女秘书。今天的故事又开始了:

话说有位上世纪80年代下海创业成功的大老板,但是呢,文化程度不高,随着历史的车轮滚滚向前,也随着公司越做越大,公司的业务也在逐步扩大,准备开拓海外市场,他想找个翻译最好也能辅助一下自己的工作,一是托朋友四处打探,终于找到了这么一位年轻貌美,能力极强的秘书。经过老板与秘书的配合,最终成功拓展了海外市场,让公司做大做强。(故事纯属瞎….,我就不信有雷同)

女秘书的能力到底有哪些呢?

  • 翻译能力
  • 文件整理能力
  • 关联文件,工具的查找与使用的能力
  • 归纳总结的能力
  • 思维灵活

我们都知道,构建工具 webpack 现如今也是各大公司炙手可热的"大红具",虽然各种工具还在层出不穷,但 webpack 至少现在还是年富力强,所以还是学学吧。

webpack 的能力:

  • 编译能力:webpack 可以把前面提到 JSX 等浏览器不能识别的代码编译成 JavaScript,Babel 也支持 ESNext 句法,一句话就是 webpack 可以把 各种文件编译成浏览器可以识别的代码。
  • 代码整理能力:webpack 可以把代码拆分,进行按需加载,也可以把代码合并,简化代码,让文件更少,更小。
  • 依赖管理:webpack 能把各个文件间的依赖逐一进行解读,编译,整合,以及一些三方插件的引入。
  • 模块管理:构建高效,简单,可复用的组件,最后将组件合并为一个完整的应用。
  • 热更新能力:监听源码变化,立即更新有变化的模块。这一点在前端的开发,调试中省去了多少的 Ctrl + F。

webpack 构建项目

我们通过构建一个 React 项目来进一步了解 webpack。

  1. 我们先打开终端,在合适的位置上创建一个 weekplan-app 项目文件夹;
mkdir weekplan-app
cd weekplan-app
  1. 创建项目 和 package.json 文件;
npm init -y

此刻可以看看项目文件夹里边是不是多了 package.json 文件了。

  1. 安装 react 和 reactDOM;
npm install react react-dom serve

目前,weekplan-app 文件夹下就多了 node_modules 文件夹,package-lock.json 文件;

”高级女秘书“ —— webpack 创建一个 React 应用

  1. 打开代码编辑器我们来把项目文件按如下结构补全;

”高级女秘书“ —— webpack 创建一个 React 应用

  • 在 originalData 下创建 planList.json 文件:
[  {    "title": "周一的计划", "index": 1, "todoItems": [      { "index": 1, "time": "7:00 PM", "matters": "运动健身" },      { "index": 2, "time": "9:00 PM", "matters": "阅读" }    ]
  },
  {
    "title": "周二的计划", "index": 2, "todoItems": [
      { "index": 1, "time": "7:00 PM", "matters": "练习萨克斯" },
      { "index": 2, "time": "8:00 PM", "matters": "看一部电影" }
    ]
  },
  {
    "title": "周三的计划", "index": 3, "todoItems": [
      { "index": 1, "time": "7:00 PM", "matters": "练习毛笔字" },
      { "index": 2, "time": "8:00 PM", "matters": "短距离夜骑" }
    ]
  },
  {
    "title": "周四的计划", "index": 4, "todoItems": [
      { "index": 1, "time": "7:00 PM", "matters": "运动健身" },
      { "index": 2, "time": "8:00 PM", "matters": "高数学习" }
    ]
  },
  {
    "title": "周五的计划", "index": 5, "todoItems": [
      { "index": 1, "time": "7:00 PM", "matters": "云顶之奕" }
    ]
  },
  {
    "title": "周六的计划", "index": 6, "todoItems": [
      { "index": 1, "time": "7:00 AM", "matters": "绿道骑行" },
      { "index": 2, "time": "7:00 PM", "matters": "线代学习" }
    ]
  },
  {
    "title": "周日的计划", "index": 7, "todoItems": [
      { "index": 1, "time": "8:00 AM", "matters": "学习,整理,总结" },
      { "index": 2, "time": "3:00 PM", "matters": "追番,追剧,追综艺" }
    ]
  }
]
  • 在 components 文件夹下创建 TodoItems.js 文件,WeekPlan.js 文件:
// TodoItems.js 
import React from "react";

const TodoItems = ({ todoItems }) => (
    <ul>
        { todoItems.map(item => (
                /* 定义标签 class 属性时,JSX 中要用 className,因为 class 是 JavaScript 声明 类的保留字 */
                <li clsssName="todo-item" key={item.index}>{ `${item.time}:${item.matters}` }</li>
            )
        )}
    </ul>
);

export default TodoItems;
// WeekPlan.js
import React from "react";
import TodoItems from "./TodoItems";

const WeekPlan = ({ weekPlanList }) => (
    weekPlanList.map(weekPlan => (
        <React.Fragment key={weekPlan.index}>
            <h2>{weekPlan.title.replace('的', '') + ':'}</h2>
            <TodoItems {...weekPlan} />
        </React.Fragment>
    ))
);

export default WeekPlan;

在组件中,导出用 export,导入组件用 import,这里我们可以拓展一下

  • export:主要用于暴露文件部分对象,且可以同时暴露多个。

  • export default:暴露文件内部所有对象。

  • import {} from "...": 接受 export 暴露的所有对象,接受对象的名称不能自定义,但可以接 as 来自定义对象名称。

  • import customName form "...": custTomName 可以为自定义名称。

  • 来看个例子就很好理解了:

  • // exportExample.js
    export const author = "export:炭烤小橙微辣";
    
    const getAuthor = () => {
      return `export default: ${author}`;
    };
    
    export default getAuthor;
    
    import { author } from "./exportExample";
    import getAuthor from "./exportExample";
    import getAuthorByExample from "./exportExample";
    import { author as authorAs } from "./exportExample";
    import * as authorByAll from "./components/test";
    
    console.log(author); // export:炭烤小橙微辣
    console.log(getAuthor()); // export default:炭烤小橙微辣
    console.log(getAuthorByExample()); // export default:炭烤小橙微辣
    console.log(authorAs); // export:炭烤小橙微辣
    console.log(authorByAll.author); // export:炭烤小橙微辣
    

    module.exports 的导出与导入请看前边的文章《JavaScript 新特性》,这里就不再多赘述了。

  • 在 src 目录下创建 index.html 文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>周计划</title>
</head>
<body>
 <div id="root"></div>
</body>
</html>
  • 在 src 目录下创建 index.js 文件:
import React from "react";
import { createRoot } from "react-dom/client";
import WeekPlan from "./components/WeekPlan";
import planList from "./originalData/planList.json"

const root = createRoot(document.getElementById("root"));
root.render(<WeekPlan weekPlanList={planList} />);

把组件,数据文件都配置好了,就可以配置 webpack 打包的相关配置了。

我们安装 webpack,webpack-cli,在项目定义webpack版本,这样,webpack

npm install webpack webpack-cli --save-dev

局部安装:对项目定义 webpack 版本,打包的时候就不会出现包版本的问题了。

webpack-cli 是 webpack 的执行依赖,在 webpack-cli 中代码执行时,才是 webpack 进行编译和打包的过程。

那么 webpack 是怎样进行项目打包的呢?

当我们运行webpack时, webpack 会 查找当前目录下的 src/index.js 作为入口,然后从入口开始,会生成一个依赖关系图,这个关系图包含程序中所需的模块(js,css,图片等)然后历遍结构,打包一个个模块,其中会用到 loader 来解析不同文件来进行相应的解析。

我们知道 JSX 等文件需要编译才能被浏览器识别,这个时候有一个 叫做 Babel 的转换器,我们先安装 Babel 依赖:

npm install babel-loader @babel/core --save-dev

安装 babel 预设:提前定义 bable 把 JSX,ESNext 语句转换成什么类型的语句。

npm install @babel/preset-env @babel/preset-react --save-dev

我们在根目录新建一个 .babelrc 文件: 这个文件主要就是为 babel 提供编译规则,presets 数组中,越靠后的越先执行;

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

下边对这几个插件及依赖进行一个简单的介绍:

  • babel-loader: 解析 ESNext,JSX 等语句的桥梁。
  • @babel/core: 根据(.babelrc)中的规则,进行源码的转换。
  • @babel/preset-env:提供 ESNext 转换为 ES5 的语法转换规则。
  • @babel/preset-react: 对react语法的转换。

Babel 功能及其强大,对于 Babel 的详细介绍,感兴趣的 jym 可以看看 Babel的文档

最后一步,安装插件 html-webpack-plugin, webpack-serve-dev

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

webpack-serve-dev: 本地开发工具,本地可以直接启用服务来查看页面。

在使用 webpack 构建时,我们需要把 JSX 转换成 React 元素。需要新建一个配置文件: webpack.config.js(自定义打包配置文件), 这个文件名字固定,webpack 打包之前会解析这个文件,以获取打包的自定义配置。

// webpack.config.js
// path 为 Node.js 内置 npm 模块,只要为了更方便的处理文件或目录路径
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
    entry: "./src/index.js", // 项目入口
    devtool: "source-map", // 源码映射,方便使用源码调试
    output: {
        path: path.join(__dirname, "dist"), // 打包根目录下创建一个文件dist文件夹,里边是打包好的文件
        filename: "bundle.js" // 所有的 react,JSX,EXNext 代码 都将被编译打包进这个文件
    },
    module: {
        rules: [
            // 在所有导入的除 node_modules 文件夹中的 JavaScript 文件上运行 babel-loader
            {test: /.js$/, exclude: /node_modules/, loader: "babel-loader"}
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            // 以public下index.html 为模版打包生成html文件, 打包的 js 文件 或其他 css 等文件,并在 这个文件中插入一个
            // script 标签,标签的地址就是上边的 output.filename
            template: path.resolve(__dirname, 'src/index.html')
        })
    ]
}

最后配置 package.json 中的 scirpts 对象:

{
  "test": "echo "Error: no test specified" && exit 1",
  "build": "webpack --mode production",
  "dev": "webpack --mode develoment",
  "start": "webpack-dev-server --open --mode development"
}

现在所有配置都已完成,现在想看到自己写的周计划项目的话,只需要在终端 输入命令:

npm run start

等服务启动成功,就可以在浏览器地址为 http://localhost:8080/ 的页面看到自己写的周计划啦!

”高级女秘书“ —— webpack 创建一个 React 应用

我们可以把项目打包到 dist 文件夹下,执行如下命令:

npm run build

经过打包过后,就多出来一个 dist 文件夹,里边的也就是打包过后的文件。

”高级女秘书“ —— webpack 创建一个 React 应用

总结

我们这么大费周章的通过对 webpack,Babel 等工具的简单介绍,然后一步一步创建一个 React 应用,目的其实很简单,就是希望大家对从头创建一个 React 项目有所了解,虽然现在有更便捷创建 React 应用的方式,但是,这就是创建一个 React 项目的基础,当然,要创建一个应用级的项目,这些配置肯定是不够的,里边还有很多需要配置,比如 ESlint,router,state 等等,这也算是一个抛砖引玉的过程吧。

拓展: 作为一个 React 开发者, Create React App 这个工具能够帮助开发者快速创建 React 项目。 可以全局安装 Create React App包(不想安装:直接执行 npx create-react-app my-project):

npm install create-react-app -g

安装成功后,就可以通过这个包来创建更加健全的 React 应用了。

create-react-app my-project