背景
如下图所示,所有的前端项目都要经历静态资源下载 + JS解析与执行这个过程。而对于当今流行的React/Vue项目来说,一个App组件往往是很大的,仅仅执行 import App from './App'; 这段代码,就需要较长的耗时,下图是一个中型项目的APP初始化过程,大约需要250+ms。这250ms内,整个网络线程是完全空闲的状态。那么我们思考能不能把一些业务请求放在这部分时间来做呢?
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
优点
1、完全不干扰业务原本的写法,只需要额外增加一个preRequest的逻辑即可,这部分逻辑是完全可插拔的
2、当前市面上也有一些使用缓存的axios插件,但仅仅是缓存内容,并且都没有处理请求发出未返回这种场景。
使用方法
安装
npm install axios-pre-request --save-dev
ajax预取
1、使用axios方式进行预取
优点:业务改动小,请求功能完善,API完全和axios一致。
缺点:必须依赖axios,不太方便将预取代码inline化
import axios from 'axios';
import preAxios from 'axios-pre-request/src/preAxios';
const preRequest = preAxios(axios);
preRequest({url: '/mock/menus.json', params: {a:1, b:2}});
2、使用fetch方式进行预取
优点,不依赖任何请求库,方便将预取代码直接inline到html中,进一步提前预取时机。
缺点:请求功能轻量,相比axios等完整度不够。
import preRequest from 'axios-pre-request/src/preRequest';
preRequest({url: '/mock/menus.json', params: {a:1, b:2}});
2.1、使用fetch方式进行预取并inline化
const HtmlInlineScriptPlugin = require('html-inline-script-webpack-plugin');
entry: {
preRequest: './src/request',
main: './src/index'
},
output: {
filename: isEnvProduction
? 'static/js/[name].[contenthash:8].js'
: isEnvDevelopment && 'static/js/[name].js',
},
plugins: [
new HtmlWebpackPlugin(),
new HtmlInlineScriptPlugin({
scriptMatchPattern: [/preRequest/],
}),
]
axios拦截
import axios from 'axios';
import wrapper from 'axios-pre-request';
const axiosInstance = wrapper(axios);
高级配置
import preRequest from 'axios-pre-request/src/preRequest';
preRequest({url: '/mock/menus.json', params: {a:1, b:2}}, {
ttl: 10000,
useTime: 1,
cb: (key, data, response) => {
if (!data instanceof Error) {
if (data.code !== 200) {
preRequestCache[key].state = 'failed';
}
}
},
});
消费次数配置(useTime)
可以配置预取到的内容只消费一次或n次,避免对后续的业务逻辑产生副作用。
失效时间配置(ttl)
可以配置预取到的内容的缓存时间,避免对后续的业务逻辑产生副作用。
业务状态码配置(cb)
可以配置业务状态码,避免业务上的异常内容被缓存。