持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情
很多时候我们会用react的脚手架来构建我们的项目,这种单页面富应用在现在很流行,但是也有一个问题就是首屏加载的时间太长了,由于一般都是通过webpack来打包构建我们的项目,最终会变成对应的js,css,html等文件,在首次加载的时候就会出现长时间的白屏,那么用户的体验就很不好,所以怎么优化体验也是性能优化要考虑的一方面。
方案
介绍一种一种治标不治本的方式,既然首屏加载时间长会导致长时间的白屏导致用户等的不耐烦就走了,那么我们在加载的文件大小不变的情况下,如果可以在加载完成前先进行一部分内容的展现是不是就可以有所改善呢?
方法
我们借助html-webpack-plugin来实现我们的需求,首先我们要知道,我们的react最终打包生成的文件是在dist文件夹中的index.html中进行引入的,一般在index.html中会有一个id为root的节点,在文件加载结束的时候我们的整个节点内容就会被替换掉,那么没加载前自然就是root原来的内容,那么想象一下,现在首屏加载需要很久,但是你的root不是一个空白节点,而是内容酷炫的加载动画,这样用户的体验会不会好很多呢?那么这个html-webpack-plugin是什么来头?有什么用呢?因为正常的业务中是有很多个页面的,如果每个每页都需要我们复制粘贴这个加载动画,就不太合理了,所以我们使用其来自动化实现我们的需求。
实现
由于这涉及到了webpack的操作,而我们的create-react-app一般是不暴露我们的webapck的配置的,如果强制eject又不那么优雅了,所以我们打算使用直接搭建的简单脚手架来实现我们的操作,在此之前我们前面的文章已经搭建过vue的简单版脚手架了,编程react无非就是loader和库的引入有些许不同。
项目构建
npm init初始化我们的项目后,我们安转下面的依赖
构建如下的项目目录结构
index.js内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root"></div>
<script src="boundle.js"></script>
</body>
</html>
App.js
import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div>
test
</div>
);
}
}
export default App;
main.js
import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div>
test
</div>
);
}
}
export default App;
.babelrc
{
"presets": [
["@babel/env", {
// 指定需要兼容的浏览器类型和版本
"targets": {
"browsers": ["last 2 versions"]
}
}],
"@babel/react" // 解析jsx
]
}
webpack.config.js
const path = require("path");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "boundle.js",
},
module: {
rules: [
{
test: /\.s[ca]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.m?js|jsx$/,
use: [
{
loader: "babel-loader",
options: {
presets: ["@babel/preset-env","@babel/preset-react"],
},
},
],
},
],
},
devServer: {
static: {
directory: path.resolve(__dirname, 'dist'),
},
compress: true,
port: 9000,
},
};
这样操作完一个简单的react脚手架我们就完成了。
优化
接下来我们就是要进行首屏优化了,先安装这个插件,然后修改我们的配置
const path = require("path");
var HtmlWebpackPlugin = require("html-webpack-plugin");
const fs = require("fs");
var loading = {
html: fs.readFileSync(path.join(__dirname, "./loading.html")),
css:
"<style>" +
fs.readFileSync(path.join(__dirname, "./loading.css")) +
"</style>",
};
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "boundle.js",
},
module: {
rules: [
{
test: /\.s[ca]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.m?js|jsx$/,
use: [
{
loader: "babel-loader",
options: {
presets: ["@babel/preset-env", "@babel/preset-react"],
},
},
],
},
],
},
devServer: {
static: {
directory: path.resolve(__dirname, "dist"),
},
compress: true,
port: 9000,
},
plugins: [
new HtmlWebpackPlugin({
template: "./dist/index.html",
filename: "./loading.html",
inject: "body",
loading: loading,
}),
],
};
注意这里要创建对应的文件
loading.html和loading.css
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./loading.css">
</head>
<body>
<div class="loading">loading</div>
</body>
</html>