《Webpack5 核心原理与应用实践》学习笔记-> React全栈环境

简介: 《Webpack5 核心原理与应用实践》学习笔记-> React全栈环境


搭建react开发环境为全新环境,这里只讲搭建react环境,不再包含lesscss等,只要不使用这些东西一样可以构建出来,因为这些之前都有讲过,再写就有点凑字数和废话,好学的可以看历史章节。


搭建react环境



这次搭建为从零开始,不包含开发环境,而且直接跳过.jsx,直接使用.tsx


  • 新建一个项目(就是目录),随便取个名字。
  • npm init -y生成一个package.json
  • 初始化webpack,命令行npm i -D webpack webpack-cli
  • 根目录下创建webpack.config.js,内容如下


const path = require("path");
module.exports = {
    mode: "production",
    entry: './src/index.tsx',
    output: {
        filename: "[name].js",
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        rules: [
            {
                test: /.tsx$/,
                use: [
                    {
                        loader: 'babel-loader',
                        options: {
                            presets: [
                                '@babel/preset-env',
                                [
                                    '@babel/preset-react',
                                    { pragma: 'createElement' },
                                ],
                            ],
                        },
                    },
                    { loader: 'ts-loader' },
                ],
            },
        ]
    },
    resolve: {
        extensions: ['.tsx'], // 这个可以让webpack默认入口的文件类型(.js/.json/.wasm)新增额外类型
    }
}

从上面的配置可以看到我们要安装解析.tsx的配置,需要安装很多依赖,babel-loader@babel/preset-env@babel/preset-reactts-loader等。


  • 安装babelnpm i -D babel-loader @babel/core @babel/preset-env
  • 安装ts: npm i -D typescript ts-loader
  • 安装babelreact的支持:npm i -D @babel/preset-react @babel/plugin-transform-react-jsx
  • 安装react: npm i react(这里没有加-D,因为react是要放在生产环境中的,但是课程中都是有-D的,而且确实加不加都能构建出来,都能运行)


上面的依赖就是目前recat环境所需要的全部依赖了,如果你还需要使用css,实际项目中是一定需要的,就需要安装解析css的相关依赖了,还需要加上对应的配置,这个之前章节讲过了,就没有相关的代码和演示。


  • 新建tsconfig.json配置,内容如下


{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es5",
    "sourceMap": true,
    "jsx": "react"
  },
  "exclude": [
    "node_modules"
  ]
}

  • 新建src目录
  • src下面新建index.tsx,内容如下


import React from 'react';
const Component = () => {
  return <div className="hello">hello world</div>
}

  • 运行npx webpack构建项目,可以看到会生成dist目录


可以增加一个html-webpack-plugin生成.html文件,用来查看构建出来的内容是否正确,也可以增加一个webpack-dev-server试试开发环境和热更新效果。


以上就完成了对react环境的搭建


react服务端渲染


Vue服务端渲染时已经介绍过服务端渲染的概念,所以这里略过。 recat服务端渲染和Vue类似,所以目录结构都是一样的,还是还是用一个新的工程来记录。


  • 创建react-ssr目录
  • npm init -y生成package.json
  • 根目录下新建src目录
  • src下面新建entry-client.tsx,内容如下
import { createRoot } from 'react-dom/client';
import App from './App';
const container = document.getElementById('app');
const root = createRoot(container);
root.render(<App />);

  • src下面新建entry-server.tsx,内容如下


import React from 'react'
import App from './App'
import { renderToString } from 'react-dom/server';
export default () => {
    return renderToString(<App/>);
}

  • src下面新建App.tsx,内容如下


import React, { useState } from 'react';
import './App.css';
const App = () => {
    const [isActivity, setIsActivity] = useState(false);
    const handleClick = () => {
        setIsActivity(!isActivity);
    };
    return (
        <div>
            <h3 className={`main ${isActivity ? 'activate' : 'deactivate'}`}>Hello World</h3>
            <button onClick={handleClick}>Toggle</button>
        </div>
    );
};
export default App;

  • src下面新建App.css,内容如下


h3 {
    color: #42b983;
}
.main {
    padding: 20px 12px;
    transition: background 0.3s linear;
}
.activate {
    background: #000;
}
.deactivate {
    background: #fff;
}

上面已经完成了对react的页面构建,这一块和Vue的服务端渲染很相似,接下来就是对webpack的配置

  • 根目录下新建webpack.base.js,内容如下


module.exports = {
    mode: "production",
    module: {
        rules: [
            {
                test: /.tsx$/,
                use: [
                    {
                        loader: 'babel-loader',
                        options: {
                            presets: [
                                '@babel/preset-env',
                                [
                                    '@babel/preset-react',
                                    { pragma: 'createElement' },
                                ],
                            ],
                        },
                    },
                    { loader: 'ts-loader' },
                ],
            },
        ]
    },
    resolve: {
        extensions: ['.js', '.jsx', '.tsx'],
    }
}

上面的配置就是上面讲react环境的配置,没想到这么快就用上了,而且还是作为基础配置来使用的。


  • 根目录下新建webpack.client.js(客户端文件生成的webpack配置),内容如下


const Merge = require("webpack-merge");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { WebpackManifestPlugin } = require("webpack-manifest-plugin");
const base = require("./webpack.base");
// 继承自 `webpack.base.js`
module.exports = Merge.merge(base, {
    entry: {
        // 入口指向 `entry-client.js` 文件
        client: path.join(__dirname, "./src/entry-client.tsx"),
    },
    output: {
        filename: 'index.js',
        publicPath: "/",
    },
    module: {
        rules: [{ test: /.css$/, use: [MiniCssExtractPlugin.loader, "css-loader"] }],
    },
    plugins: [
        // 这里使用 webpack-manifest-plugin 记录产物分布情况
        // 方面后续在 `server.js` 中使用
        new WebpackManifestPlugin({ fileName: "manifest-client.json" }),
        // 生成CSS文件
        new MiniCssExtractPlugin({
            filename: 'index.[contenthash].css'
        }),
        // 自动生成 HTML 文件内容
        new HtmlWebpackPlugin({
            templateContent: `
    <!DOCTYPE html>
    <html>
    <head>
  <meta charset="utf-8">
  <title>Webpack App</title>
    </head>
    <body>
  <div id="app" />
    </body>
    </html>
  `,
        }),
    ],
});

  • 根目录下新建webpack.server.js(服务端文件生成的webpack配置),内容如下


const Merge = require("webpack-merge");
const path = require("path");
const base = require("./webpack.base");
module.exports = Merge.merge(base, {
    entry: {
        server: path.join(__dirname, "./src/entry-server.tsx"),
    },
    target: "node",
    output: {
        // 打包后的结果会在 node 环境使用
        // 因此此处将模块化语句转译为 commonjs 形式
        libraryTarget: "commonjs2",
        filename: 'server.js'
    },
    module: {
        rules: [{
            test: /.css$/,
            loader: './loader/removeCssLoader'
        }]
    },
});

这里有一个细节,就是.cssloader是自己的写的,因为服务端只需要生成页面,不需要管css的生成,这里会写一个空的css-loader

  • 根目录下新建目录loader
  • loader目录下新建文件removeCssLoader.js,内容如下


module.exports = () => {
    return 'module.exports = () => null';
};

  • 根目录下新建tsconfig.json,内容如下


{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es5",
    "sourceMap": true,
    "jsx": "react-jsx"
  },
  "exclude": [
    "node_modules"
  ]
}

课程里面讲的js版本的,我这里实践是ts版本的,所以会多一点东西。


接下来就是构建项目了,可以使用npx webpack --config webpack.client.jsnpx webpack --config webpack.server.js分别构建出客户端资源和服务端资源,我这里还是将这两个命令放到了package.json文件中,如下


"scripts": {
  "build:client": "npx webpack --config ./webpack.client.js",
  "build:server": "npx webpack --config ./webpack.server.js",
},

接下来就可以使用npm run build:clientnpm run build:server来构建客户端和服务端资源了。


搭建node服务验证效果


这里还是和vue服务端渲染一样,使用express来作为服务端。


  • 在根目录下新建server.js,内容如下


const express = require('express');
// 通过 manifest 文件,找到正确的产物路径
const clientManifest = require("./dist/manifest-client.json");
const server = express();
server.get("/", (req, res) => {
    const html = require('./dist/server.js').default;
    const clientCss = clientManifest["client.css"];
    const clientBundle = clientManifest["client.js"];
    res.send(`
<!DOCTYPE html>
<html>
    <head>
      <title>React SSR Example</title>
      <link rel="stylesheet" href="${clientCss}"></link>
    </head>
    <body>
      <!-- 注入组件运行结果 -->
      <div id="app">${html()}</div>
      <!-- 注入客户端代码产物路径 -->
      <!-- 实现 Hydrate 效果 -->
      <script src="${clientBundle}"></script>
    </body>
</html>
    `);
});
server.use(express.static("./dist"));
server.listen(3000, () => {
    console.log("服务启动成功:http://localhost:3000");
});

接下来就可以运行node server.js来启动服务啦,但是为了方便我这里将所有的命令一站式封装到package.json中了,这里还是因为依赖太多,所以服务端渲染这一块没有讲依赖安装的环节,这里还是直接上package.json


{
  "name": "react-ssr",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build:client": "npx webpack --config ./webpack.client.js",
    "build:server": "npx webpack --config ./webpack.server.js",
    "server": "node ./dist/server.js",
    "run": "npm run build:client && npm run build:server && node server.js",
    "test": "echo "Error: no test specified" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.18.10",
    "@babel/plugin-transform-react-jsx": "^7.18.10",
    "@babel/preset-env": "^7.18.10",
    "@babel/preset-react": "^7.18.6",
    "babel-loader": "^8.2.5",
    "css-loader": "^6.7.1",
    "express": "^4.18.1",
    "html-webpack-plugin": "^5.5.0",
    "mini-css-extract-plugin": "^2.6.1",
    "ts-loader": "^9.3.1",
    "typescript": "^4.7.4",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "webpack": "^5.74.0",
    "webpack-cli": "^4.10.0",
    "webpack-manifest-plugin": "^5.0.0",
    "webpack-merge": "^5.8.0"
  }
}

现在可以使用npm run run来一站式构建客户端、服务端资源和启动服务啦,瑞思拜。


总结


没什么好总结的,今天不上课程里面的总结了,Vue的服务端渲染是直接对着课程来的,很顺利。

react的服务端渲染对着课程来报错了,不是因为我使用ts版的问题,是构建出来的资源无法运行,后来将架构改成和Vue版一致的就好了。


使用ts版的也是个人的拓展练习,准备webpack学完就深入ts了。


课程中建议这些东西不要自己折腾,可以直接使用比较成熟的Create React App,当然使用归使用,练习和学习还是自己来,这样就可以知其然且知其所以然。


示例代码:react-ssr


目录
相关文章
|
25天前
|
前端开发 JavaScript
手敲Webpack 5:React + TypeScript项目脚手架搭建实践
手敲Webpack 5:React + TypeScript项目脚手架搭建实践
|
2月前
|
JavaScript 测试技术 Windows
vue配置webpack生产环境.env.production、测试环境.env.development(配置不同环境的打包访问地址)
本文介绍了如何使用vue-cli和webpack为Vue项目配置不同的生产和测试环境,包括修改`package.json`脚本、使用`cross-env`处理环境变量、创建不同环境的`.env`文件,并在`webpack.prod.conf.js`中使用`DefinePlugin`来应用这些环境变量。
107 2
vue配置webpack生产环境.env.production、测试环境.env.development(配置不同环境的打包访问地址)
|
1月前
|
存储 前端开发 测试技术
React Hooks 的工作原理
【10月更文挑战第1天】
|
3月前
|
前端开发 算法 JavaScript
React原理之Diff算法
【8月更文挑战第24天】
|
6月前
|
存储 前端开发 中间件
🚀React+Node全栈无死角解析,吃透文件上传的各个场景
🚀React+Node全栈无死角解析,吃透文件上传的各个场景
|
3月前
|
前端开发 JavaScript 算法
如何学习react原理
【8月更文挑战第9天】 如何学习react原理
45 6
|
3月前
|
开发者 安全 UED
JSF事件监听器:解锁动态界面的秘密武器,你真的知道如何驾驭它吗?
【8月更文挑战第31天】在构建动态用户界面时,事件监听器是实现组件间通信和响应用户操作的关键机制。JavaServer Faces (JSF) 提供了完整的事件模型,通过自定义事件监听器扩展组件行为。本文详细介绍如何在 JSF 应用中创建和使用事件监听器,提升应用的交互性和响应能力。
37 0
|
3月前
|
前端开发 Java UED
瞬间变身高手!JSF 与 Ajax 强强联手,打造极致用户体验的富客户端应用,让你的应用焕然一新!
【8月更文挑战第31天】JavaServer Faces (JSF) 是 Java EE 标准的一部分,常用于构建企业级 Web 应用。传统 JSF 应用采用全页面刷新方式,可能影响用户体验。通过集成 Ajax 技术,可以显著提升应用的响应速度和交互性。本文详细介绍如何在 JSF 应用中使用 Ajax 构建富客户端应用,并通过具体示例展示 Ajax 在 JSF 中的应用。首先,确保安装 JDK 和支持 Java EE 的应用服务器(如 Apache Tomcat 或 WildFly)。
44 0
|
3月前
|
缓存 JavaScript 前端开发
【React生态进阶】React与Redux完美结合:从原理到实践全面解析构建大规模应用的最佳策略与技巧分享!
【8月更文挑战第31天】React 与 Redux 的结合解决了复杂状态管理的问题,提升了应用性能。本文详细介绍了在 React 应用中引入 Redux 的原因、步骤及最佳实践,包括安装配置、状态管理、性能优化等多方面内容,并提供了代码示例,帮助你构建高性能、易维护的大规模应用。
58 0
|
3月前
|
前端开发 JavaScript 中间件
【前端状态管理之道】React Context与Redux大对决:从原理到实践全面解析状态管理框架的选择与比较,帮你找到最适合的解决方案!
【8月更文挑战第31天】本文通过电子商务网站的具体案例,详细比较了React Context与Redux两种状态管理方案的优缺点。React Context作为轻量级API,适合小规模应用和少量状态共享,实现简单快捷。Redux则适用于大型复杂应用,具备严格的状态管理规则和丰富的社区支持,但配置较为繁琐。文章提供了两种方案的具体实现代码,并从适用场景、维护成本及社区支持三方面进行对比分析,帮助开发者根据项目需求选择最佳方案。
62 0
下一篇
无影云桌面