按需加载

随着 web 网页的流行,越来越多的人选择使用网页来代替传统的 APP,随之而来的就是网页越来越庞大,前端性能的问题尤其显现。一些大的项目都会做一些性能优化来提高访问速度,以提升用户的体验,比如:按需加载,资源优化等。

按需加载可以提高页面加载速度,如果当前页面只使用了某个功能,我们可以选择只加载这个功能,避免过于庞大的包加载进页面而需要等等过长的时间。

接下来我们先讨论一个问题:什么时候需要按需加载呢?

如果打包的产物是一个文件,这个文件又很大,一次性下载下来的速度就会比较慢,可能会造成刚进入页面时长时间的白屏的情况,这种体验非常不好;如果打包成多个文件,但是浏览器在同一时间内可以发出的请求数有限制,这也会导致用户等待。按需加载就可以很好的去解决这些问题。

那么我们如何按需加载呢?

简单有效的方式是使用 babel-plugin-import

什么是 babel-plugin-import?

babel-plugin-import 是阿里开源的一款 babel 插件,它会在编译过程中将 import 的写法自动转换为按需引入的方式,主要用于组件的按需引入。

如何在项目中添加 babel-plugin-import?

使用方法

安装

npm install babel-plugin-import --save-dev

配置

通过 .babelrc 配置文件或者 babel-loader 引入。

{
  "plugins": [["import", options]]
}

其中 options 为具体的配置项

如果使用 babel7,可以做如下的配置:

{
  "plugins": [["import", options, "antd"]]
}

接下来一起看看具体的配置项 options

{
  "libraryName": "antd",
  "style": true,   // or 'css' or 'function'
  "libraryDirectory": "components",  // default: lib
  "camel2DashComponentName": false,  // default: true
  "styleLibraryDirectory": "lib",
  "customName": (name: string, file: object) => {
        const filename = file.opts.filename;
        if (name === 'TimePicker'){
          return 'antd/lib/custom-time-picker';
        }
        if (filename.indexOf('/path/to/my/different.js') >= 0) {
          return 'antd/lib/custom-name';
        }
        return `antd/lib/${name}`;
      }
}
  • libraryName 代表库的名称

  • style 引入样式,可以指定 css、true 或者 function

  • libraryDirectory 组件所在目录,默认:lib

  • camel2DashComponentName 将引入的组件名转化为"-"连接的文件名

  • styleLibraryDirectory 样式文件路径

  • customName 自定义导入文件路径,也可以是一个文件,例如:require('path').resolve(__dirname, './customName.js')

customName.js 文件如下:

module.exports = function customName(name) {
  return `antd/lib/${name}`;
};

使用示例

上来讲述了使用方法,我们一起来看看配置后的结果吧!

{ "libraryName": "antd" }
import { Button } from 'antd';
import { TimePicker } from "antd"

ReactDOM.render(<Button>xxxx</Button>);

// 最后输出结果
var _button = require('antd/lib/button');
var TimePicker = require('antd/lib/time-picker');

ReactDOM.render(<_button>xxxx</_button>);

上面只配置了libraryNameantd,按照默认路径 lib 引入组件。

{ "libraryName": "antd", style: "css" }
import { Button } from 'antd';
ReactDOM.render(<Button>xxxx</Button>);

// 最后输出结果
var _button = require('antd/lib/button');
require('antd/lib/button/style/css');
ReactDOM.render(<_button>xxxx</_button>);

配置 style: "css",直接引入经过打包后的 antd 样式文件

{ "libraryName": "antd", style: true }
import { Button } from 'antd';
ReactDOM.render(<Button>xxxx</Button>);

// 最后输出结果
var _button = require('antd/lib/button');
require('antd/lib/button/style');
ReactDOM.render(<_button>xxxx</_button>);

配置 style: true,在项目编译阶段,可以对引入的 antd 样式文件进行编译,从而可以压缩打包尺寸

{
    "libraryName": "antd",
    "style": (name: string, file: Object) => {
       if(name === 'antd/lib/utils'){
         return false;
       }
     return `${name}/style/2x`;
   }
}

配置 style: (name) => ${name}/style/2x,引入 css 文件路径是 ComponentName/style/2x

{
  "libraryName": "element-ui",
  "styleLibraryDirectory": "lib/theme-chalk",
}
import { Button } from 'element-ui';

// 最后输出结果
var _button = require('element-ui/lib/button');
require('element-ui/lib/theme-chalk/button');

配置 "styleLibraryDirectory": "lib/theme-chalk",指定样式在 lib/theme-chalk 目录下。

{
  "libraryName": "element-ui",
  "camel2DashComponentName": false,
}
import { TimePicker } from "antd"

// 最后输出结果
var _button = require('antd/lib/TimePicker');

配置 camel2DashComponentName: false,不会将组件名转化为"-"连接的文件名

{
    "libraryName": "antd",
    "customName": (name: string, file: object) => {
      const filename = file.opts.filename;
      if (name === 'TimePicker'){
        return 'antd/lib/custom-time-picker';
      }
      if (filename.indexOf('/path/to/my/different.js') >= 0) {
        return 'antd/lib/custom-name';
      }
      return `antd/lib/${name}`;
    }
}
import { TimePicker } from "antd"

// 最后输出结果
var _button = require('antd/lib/custom-time-picker');

配置 customName,可以根据指定路径引入组件。

现在我们可以方便地使用按需加载了,不止是开源的组件库,或者是我们自研的组件库都可以使用这种方法。但是也需要我们的组件库支持,也就是说我们的组件库要符合一定的目录结构,export 导出也要符合规范才可以。

总结

有了 babel-plugin-import 后我们可以愉快地进行开发了,只需要在项目中配置一次就不需要关心了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,783评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,396评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,834评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,036评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,035评论 5 362
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,242评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,727评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,376评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,508评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,415评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,463评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,140评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,734评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,809评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,028评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,521评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,119评论 2 341

推荐阅读更多精彩内容