书接上回,在上回的笔记中,已经完成了react的一个最简单的实践,但是这个实践还有很多问题,这次我们来解决一下这些问题。

在这回我们主要解决项目在开发时的热更新问题和css的加载问题,顺便把这个项目目录改一改,让他改的像个正经的项目,而不是用于验证可行性的玩具。

开发中的热更新

在做react的开发的时候,大家肯定非常熟悉webpack-hot-server给我们提供的热更新,他启动了一个node服务,在本地的某个端口可以访问到我们开发的页面,并提供一个监控,在我们的文件发生变动之后,自动打包编译并展示新的内容在相应的端口上。

但是换到我们做SSR的时候,这一套就不能使用了,我们需要用新的一套解决方案。

解决方案分客户端和服务端,毕竟我们其实是开启了两个服务,只不过服务端的热更新我们是用nodemon来实现的

那么nodemon又是个什么东西呢?

nodemon就是一个用来替代node的包,不需要任何的配置(当然可以配置),就可以监控项目文件的变化,并在文件发生改变的时候,自动的重启服务。

是不是感觉特别智能,使用前首先要下载,因为这个东西在所有的项目中都可以用,所以推荐直接全局安装

npm install nodemon -g

然后把通常启动命令由

node [你需要启动的服务入口]

改成

nodemon [你需要启动的服务入口]

然后你会发现当我们改变客户端的时候,这个服务依旧被重启了,但是并没有发生变化,这是为什么呢?

因为我们之前走的方式首先服务端读取react的组件,然后输出字符串组装成页面返回给浏览器,然后浏览器读取对打包出来的main.js然后渲染,虽然在重启后我们已经更新了对应的react组件输出的字符串,但是我们并没有改变mian.js这个东西,他仍然会渲染之前的内容。

下面我们是否应该搞客户端的热更新呢?并不是,我们要把nodemon监控的范围圈定在我们的服务端,避开客户端,不然我们每次修改客户端,迎来的都不是热更新,而是服务的重启,虽然并不耽误热更新效果,但是随着项目的变大,重启的时候是越来越长的,我们肯定不能接受改一个css整个项目直接重启了。

当然随着项目的变大,nodemon效率也会越来越低,到时候我们再更换真正的服务端热更新,优化这个东西,最好是在有需求的时候再搞。

好了,说一下nodemon的配置,他的配置其实也很简单,在项目的根目录下新建一个配置文件

mkdir nodemon.json

在文件里写入

{"ignore": ["app/"]
}

就可以忽略app文件夹内的所有文件了,后续我们重新整理项目的时候这里也要做相应的改变。

上面的都折腾完了,我们可以开始折腾我们的客户端热更新了,目前常用的解决方案大概是webpack-dev-middleware+webpack-hot-middleware来搞定客户端的热更新

首先我们下载两个依赖

npm install webpack-dev-middleware webpack-hot-middleware --save-dev

然后在我们的server.js文件中做出一些改变

我们要引入一些东西

import webpack from 'webpack';
import webpackConfig from './webpack.config'
import webpackDevMiddleware from 'webpack-dev-middleware'
import webpackHotMiddleware from 'webpack-hot-middleware'

其中weboack.config就是我们的webpack配置文件

然后添加

let compiler = webpack(webpackConfig)
server.use(webpackDevMiddleware(compiler, {publicPath: webpackConfig.output.publicPath,quiet: true
}))
server.use(webpackHotMiddleware(compiler));

这里注意到我们使用了webpackConfig.output.publicPath。但是我们好像并没有设置这个地址,这个地址可以理解为内存中的打包文件的访问入口,因为热更新的时候文件并不会真是输出在文件夹内,而是存放在内存中。然后我们去更改我们的webpack配置文件。

output: {filename: '[name].js',path: path.join(__dirname, 'dist'),publicPath: '/dist'
}

然后更改我们的模板文件template.js文件中的js文件地址,更改为/dist/main.js。

好了,现在运行

npm run start

来看看效果吧,更爱hello.js文件的内容看看会不会更新。

下面我们来搞一搞css的loader,这个就不多说了,网上教程一大把。

emmm,直到开始配置css-loader之前我都是这么以为的。然而事实我头疼了两天,一直在报错,始终无法运行css-loader。一直说css-loader找不到@babel/preset-env。

然后我下载这个依赖,依旧如此。

我还没有放弃,把@babel/preset-env下载的全局,还是没有用。最后参考了别人的依赖目录,发现了一个问题,没有人的css-loader的版本是大于2.0的,然后去官网看了看,发现2.0版本更改了很多依赖。

2.0版本他对于babel的依赖全面转到了新的@babel/core中,我懒得重新配一套babel了,就直接把css-loader降级,完美解决。

简单说一下一个最简单的less的实例吧。

首先我们在app文件夹内建立一个home.less的文件,然后填写一些内容比如

.hello{font-size:20px;
}

在我们引入这个文件 并给div一个类名

import Hello from './hello.js'
import ReactDOM from 'react-dom'
import React from 'react'
import './home.less';
ReactDOM.hydrate(<Hello />, document.getElementById('root'))
import React from 'react'
export default class Hello extends React.Component {render () {return <div onClick={this.click} className='hello'>hello worssdsdwldsas</div>}
}

less的引入最好是在最外层,这样就不用在每个模块都引入一次样式文件了,并且因为我们的服务端渲染的字符串是直接读取模块信息的,但是目前并没有给他对应的css解析能力,只有js的解析能力。

如果我们把less文件引入在hello模块中,大家可以试着看一下效果。

我们再去webpack里面配置一下css-loader

配置前我们还是要去下载对应的依赖

npm install less less-loader css-loaser

我们只需要在webpack的rule中添加以下代码

{test:/\.less$/,use:['style-loader','css-loader','less-loader']
},

我是不打算在项目中写css和sass,所以我只做了less的解析。

好了这些都搞完了,我们的css应该可以实时的更新了,但是现在的更新是css都写在mian.js里面的,但是在实际的项目中,我们通常不会这么做,因为浏览器的规则规定,js必须全部下载完才会执行,而js通常会放到整个页面的最后面,所以在项目巨大的时候,这样的状态会让页面出现光秃秃的html的情况,所以我们要把他们区分出来。让js归js,css归css。但是这样并不影响我们开发,那么我们既要让开发和生产分离了。

开发生产分离

刚刚写热更新的我们先写js,分离的时候我们反过来,先搞css,因为css相对于js是更看重分离的。

既然搞分离,那么我们最早要搞的其实应该是webpack。

那么webpack应该怎么分离呢,首先看我们之前的packjson.json里的内容,scripts里的内容就是我们平时执行的脚本,我们分离出来start和build。

"scripts": {"start": "nodemon index.js","build": "webpack",},

这是我们之前的启动脚本,启动服务端时候回自动启动webpack的热更新,但是这个功能在生产环境并没有用,所以我们要使用环境变量区分出来生产环境还开发环境。

这里我们使用的是cross-env,如果不使用这个,在mac环境下,和linux环境下也没什么问题,但是win下可能就会无法识别环境变量,我们并不能要求所有人都统一开发环境,所以最好做一下兼容。

npm i cross-env --save-dev

然后将启动脚本修改为

"start": "cross-env NODE_ENV=development nodemon index.js",

在我们所有的文件中都可以通过

process.env.NODE_ENV

来访问这个变量,对应的,我们也可以设置一个脚本启动生产环境。

"startprod": "cross-env NODE_ENV=project node index.js",

这里用node启动,因为我们有其他的东西守护进程。

说完了服务端,我们再来看客户端,客户端在开发环境下是不需要我们自己去启动的,我们需要的是生产环境的打包

之前的脚本是

"build": "webpack",

他只执行了webpack,并没有指定文件,所以他回去搜索默认的文件webpack.config.js,来启动webpack。但是我们并不想用他,并且我们要把webpack也分离出来。

因为生产环境的webpack和开发环境的webpack其实在很多地方都是相同,我们需要把相同的东西分离出来,这样我们在改两者都可以用到的东西的时候只需要改一处,不会出现改了一个忘了另一个的问题,不然这种问题一旦爆发,就是爆发在生产环境了。

既然分离webpack,那就感觉单独建立一个文件夹用来放置设置项的东西,所以我们新建一个config的文件,并在文件夹里新建三个文件。

mkdir config
touch webpack.base.js webpack.prod.js webpack.dev.js

说道分离,我们就要确认那些东西是通用,那些是特有的,目前似乎除了css都是通用的,所以我们分离

var path = require('path');const WebpackBase = {mode: 'production',entry: {main: './app/index.js'},output: {filename: '[name].js',path: path.join(__dirname, '../dist'),publicPath: '/dist'},resolve: {extensions: ['.js', '.jsx']},module: {rules: [{test: /\.jsx?$/,loaders: ['babel-loader'],},]},
}
module.exports = WebpackBase;

对于css来说,我们的开发可以不用变,生产环境用extract-text-webpack-plugin来分离css

npm i extract-text-webpack-plugin --save-dev

然后在webpack.prod.js中引入

var ExtractTextPlugin = require('extract-text-webpack-plugin');

并把这个文件中的less规则替换为

{test:/\.less$/,use: ExtractTextPlugin.extract({fallback: 'style-loader',use: ['css-loader','less-loader']})
},

然后在这一个文件的plugins中添加一个插件

new ExtractTextPlugin('main.css')

这个mian.css就是你输出的css文件了,好了上面就是关于css配置改,下面我们接着说我们的webpack分离后的文件应该是什么样子。

因为我们webpack分离了一下,在使用的时候我们还要合并他们

npm install webpack-merge --save-dev

所以对应的两个文件分别为

var base = require('./webpack.base');
var merge = require('webpack-merge');
const webpackConfig = merge(base,{module: {rules: [{test:/\.less$/,use:['style-loader','css-loader','less-loader']},]}
})
module.exports = webpackConfig
var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var base = require('./webpack.base');
var merge = require('webpack-merge');
const webpackConfig = merge(base,{module: {rules: [{test:/\.less$/,use: ExtractTextPlugin.extract({fallback: 'style-loader',use: ['css-loader','less-loader']})},]},plugins:[require('autoprefixer'),new ExtractTextPlugin('main.css')]
})
module.exports = webpackConfig

说道这里我们webpack的分离就写完了,但是记得把我们服务加载的webpack地址更改到相应的地址。还有脚本,不要拿忘记我们为什么分离他。

最后的脚本改成

"build": "cross-env NODE_ENV=project webpack --config config/webpack.prod.js",

设置他的NODE_ENV变量为project,并使用config文件夹下的webpack.prod.js作为配置文件启动webpack打包。

笔记第二章到此位置,这一章里面我们实现了开发阶段的热更新,方便了我们开发,下一章我们就要研究研究react服务端渲染的路由问题了。

哦对了,还有一些小修改我并没有在这里展示出来,因为不太重要,或者是我在写的时候忘记了,可以对照着我github看,里面每一章都会有对应的分支。

react的SSR(2)相关推荐

  1. React Umi SSR SSG 使用TypeScript的最佳实践

    说明 Umi文档对TypeScript 只字未提 (太糟糕了, 感觉像是 KPI 项目), 所以只能自己看源码 和 Github 去捞TS的定义 最终封装为一个类型IUmiPage 使用的时候只需要指 ...

  2. React + Koa 实现服务端渲染(SSR)

    ⚛️React是目前前端社区最流行的UI库之一,它的基于组件化的开发方式极大地提升了前端开发体验,React通过拆分一个大的应用至一个个小的组件,来使得我们的代码更加的可被重用,以及获得更好的可维护性 ...

  3. 我很懒,什么都没留下系列 之 教你上手React服务端渲染(React SSR) HMR

    技术栈:webpack3.9.1+webpack-dev-server2.9.5+React16.x + express4.x 前言 (好慌!可能是因为我很懒,导致...,然后,好吧,我比较懒,没有然 ...

  4. 大前端时代,如何做好C 端业务下的React SSR?\n

    React在中后台业务里已经很好落地了,但对于C端(给用户使用的端,比如PC/H5)业务有其特殊性,对性能要求比较苛刻,且有SEO需求.另外团队层面也希望能够统一技术栈,小伙伴们希望成长,那么如何能够 ...

  5. 如何在 React 18中 利用Suspense 实现 服务端渲染(SSR)

    概述 React 18 将包括对 其服务器端渲染 (SSR) 性能的架构做了改进.这些改进带来了实质性的效果,是几年来其团队工作的结晶.大多数的改进点都是在幕后进行的,但您需要了解一些选择加入机制,尤 ...

  6. React 中同构(SSR)原理脉络梳理

    随着越来越多新型前端框架的推出,SSR 这个概念在前端开发领域的流行度越来越高,也有越来越多的项目采用这种技术方案进行了实现.SSR 产生的背景是什么?适用的场景是什么?实现的原理又是什么?希望大家在 ...

  7. react全局方法_前端面试题 ---react

    高阶组件相关 什么是高阶组件,它有哪些运用? 高阶组件就是一个函数,接收一个组件,经过处理后返回后的新的组件: 高阶组件,不是真正意义上的组件,其实是一种模式: 可以对逻辑代码进行抽离,或者添加某个共 ...

  8. 【SSR】287- 从头开始,彻底理解服务端渲染原理

    本文出自「掘金社区」,欢迎戳「阅读原文」链接和作者进行技术交流 ?? 大家好,我是神三元,这一次,让我们来以 React 为例,把服务端渲染(Server Side Render,简称"SS ...

  9. 看优酷 Node 重构之路,Serverless SSR 未来可期

    在2017年底,优酷只有Passport和土豆的部分页面用Node.js,PC和H5核心页面还都是PHP模板渲染.而最近2年,基于阿里巴巴的技术体系,我们对PC.H5多端进行了技术改造.在2019年, ...

最新文章

  1. u-boot命令寻找分析--find_cmd函数
  2. Leetcode上的解法看不懂?试着用动画的方式去辅助理解
  3. eclipse中git插件配置 编辑
  4. python 数列第几项开始,数值超过1200
  5. editplus来编写SQL
  6. IoU,ROI 和 ROC,AUC区分
  7. 百度地图3.2教程(2)公交查询
  8. 《Cisco安全防火墙服务模块(FWSM)解决方案》——2.7 软件架构
  9. matlab实验符号计算答案,2014秋实验四_MATLAB的符号计算二答案
  10. 微信 oauth授权2
  11. 【SDC】StreamSets实战之路-11-基础篇- StreamSets-数据流开发- Edge数据流设计
  12. 虚拟实习项目技术架构mal总结
  13. 2016理数全国卷 T21
  14. 【面试系列三】面试是面试者与面试官的双向沟通,如何抓住面试官的小尾巴以及面试过程中需要避开的一些减分项!
  15. linux 类似winscp_winscp 有没有Linux版的
  16. 判断7张扑克牌是否含有同花顺(5张同花顺子)
  17. FACIAL阅读笔记
  18. 物性参数库查询网站集合
  19. 授人以鱼,不如授人以渔
  20. 项目介绍丨香港科技大学工学院科技领导及创业(TLE)理学硕士学位课程

热门文章

  1. java语言程序设计丁振凡ppt_Java语言程序设计(第2版)丁振凡 第2篇.ppt
  2. 达梦数据库02-DM8客户端安装与数据迁移
  3. 线性代数(9): 空间与维度
  4. 2023年【甘肃省安全员C证】考试题库及甘肃省安全员C证考试总结
  5. 中国首台千万亿次超级计算机叫什么,中国首台千万亿次超级计算机系统研制成功...
  6. Linux下搜狗输入法的皮肤的更换
  7. 抽象类与接口的区别,以及使用依据
  8. ppfilm.exe
  9. 使用Caffe尝试DeepID
  10. 流行和声(3)minor6和弦