react的SSR(2)
书接上回,在上回的笔记中,已经完成了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)相关推荐
- React Umi SSR SSG 使用TypeScript的最佳实践
说明 Umi文档对TypeScript 只字未提 (太糟糕了, 感觉像是 KPI 项目), 所以只能自己看源码 和 Github 去捞TS的定义 最终封装为一个类型IUmiPage 使用的时候只需要指 ...
- React + Koa 实现服务端渲染(SSR)
⚛️React是目前前端社区最流行的UI库之一,它的基于组件化的开发方式极大地提升了前端开发体验,React通过拆分一个大的应用至一个个小的组件,来使得我们的代码更加的可被重用,以及获得更好的可维护性 ...
- 我很懒,什么都没留下系列 之 教你上手React服务端渲染(React SSR) HMR
技术栈:webpack3.9.1+webpack-dev-server2.9.5+React16.x + express4.x 前言 (好慌!可能是因为我很懒,导致...,然后,好吧,我比较懒,没有然 ...
- 大前端时代,如何做好C 端业务下的React SSR?\n
React在中后台业务里已经很好落地了,但对于C端(给用户使用的端,比如PC/H5)业务有其特殊性,对性能要求比较苛刻,且有SEO需求.另外团队层面也希望能够统一技术栈,小伙伴们希望成长,那么如何能够 ...
- 如何在 React 18中 利用Suspense 实现 服务端渲染(SSR)
概述 React 18 将包括对 其服务器端渲染 (SSR) 性能的架构做了改进.这些改进带来了实质性的效果,是几年来其团队工作的结晶.大多数的改进点都是在幕后进行的,但您需要了解一些选择加入机制,尤 ...
- React 中同构(SSR)原理脉络梳理
随着越来越多新型前端框架的推出,SSR 这个概念在前端开发领域的流行度越来越高,也有越来越多的项目采用这种技术方案进行了实现.SSR 产生的背景是什么?适用的场景是什么?实现的原理又是什么?希望大家在 ...
- react全局方法_前端面试题 ---react
高阶组件相关 什么是高阶组件,它有哪些运用? 高阶组件就是一个函数,接收一个组件,经过处理后返回后的新的组件: 高阶组件,不是真正意义上的组件,其实是一种模式: 可以对逻辑代码进行抽离,或者添加某个共 ...
- 【SSR】287- 从头开始,彻底理解服务端渲染原理
本文出自「掘金社区」,欢迎戳「阅读原文」链接和作者进行技术交流 ?? 大家好,我是神三元,这一次,让我们来以 React 为例,把服务端渲染(Server Side Render,简称"SS ...
- 看优酷 Node 重构之路,Serverless SSR 未来可期
在2017年底,优酷只有Passport和土豆的部分页面用Node.js,PC和H5核心页面还都是PHP模板渲染.而最近2年,基于阿里巴巴的技术体系,我们对PC.H5多端进行了技术改造.在2019年, ...
最新文章
- u-boot命令寻找分析--find_cmd函数
- Leetcode上的解法看不懂?试着用动画的方式去辅助理解
- eclipse中git插件配置 编辑
- python 数列第几项开始,数值超过1200
- editplus来编写SQL
- IoU,ROI 和 ROC,AUC区分
- 百度地图3.2教程(2)公交查询
- 《Cisco安全防火墙服务模块(FWSM)解决方案》——2.7 软件架构
- matlab实验符号计算答案,2014秋实验四_MATLAB的符号计算二答案
- 微信 oauth授权2
- 【SDC】StreamSets实战之路-11-基础篇- StreamSets-数据流开发- Edge数据流设计
- 虚拟实习项目技术架构mal总结
- 2016理数全国卷 T21
- 【面试系列三】面试是面试者与面试官的双向沟通,如何抓住面试官的小尾巴以及面试过程中需要避开的一些减分项!
- linux 类似winscp_winscp 有没有Linux版的
- 判断7张扑克牌是否含有同花顺(5张同花顺子)
- FACIAL阅读笔记
- 物性参数库查询网站集合
- 授人以鱼,不如授人以渔
- 项目介绍丨香港科技大学工学院科技领导及创业(TLE)理学硕士学位课程
热门文章
- java语言程序设计丁振凡ppt_Java语言程序设计(第2版)丁振凡 第2篇.ppt
- 达梦数据库02-DM8客户端安装与数据迁移
- 线性代数(9): 空间与维度
- 2023年【甘肃省安全员C证】考试题库及甘肃省安全员C证考试总结
- 中国首台千万亿次超级计算机叫什么,中国首台千万亿次超级计算机系统研制成功...
- Linux下搜狗输入法的皮肤的更换
- 抽象类与接口的区别,以及使用依据
- ppfilm.exe
- 使用Caffe尝试DeepID
- 流行和声(3)minor6和弦