前端公共资源完全共享的畅想

在每个前端项目中,多多少少都会依赖一些第三方资源,比如QueryReactAngularcore-jsbabel-runtime;如果我们能够尽最大程度的复用这些资源,那么我们就能够节约很大的首次请求成本,无需绞尽脑汁即可显著提升首屏首次加载速度。另外提升 webpack 构建速度,扯这么多构建优化方案,就设置 externals 效果最显著;

问题由来

前端资源如果可以尽可能的使用公共 CDN 上资源,但是集团内的公共资源太少,只有一些主流的框架或库,这就导致各个团队可能会维护一份自己的公共资源 CDN。现实中使用这些 CDN 略微麻烦,比如新起一个项目就需要这么以下步骤:

  1. 看下项目中依赖的哪些流行库可以在 CDN 上找到,譬如 react,先把这个脚本插入在页面模板。开发环境需要一些警告信息,所以最好不要使用压缩脚本。

    1
    2
    <script src="//cdn.bootcss.com/react/15.0.1/react-with-addons.js"></script>
    <script src="//cdn.bootcss.com/react/15.0.1/react-dom.js"></script>

    生成环境的模板需要压缩过的脚本:

    1
    2
    <script src="//cdn.bootcss.com/react/15.0.1/react-with-addons.min.js"></script>
    <script src="//cdn.bootcss.com/react/15.0.1/react-dom.min.js"></script>
  2. 因为我们是使用 webpack 构建,所以,还需要配置 externals;形如

    1
    2
    3
    4
    5
    6
    7
    externals: {
    react: 'React',
    'react-dom': 'ReactDOM',
    'react-addons-css-transition-group': 'React.addons.CSSTransitionGroup',
    'react-addons-shallow-compare': 'React.addons.shallowCompare',
    'react-addons-transition-group': 'React.addons.TransitionGroup',
    },

    在上面 react-addons 的资源如果不指明,很可能出现某个第三方的组件库引入 react-addons,导致 react 依旧被打包在一起。

  3. 维护需要人工成本。 如果哪一天要升级 react 版本,看到 CDN 上有新版本,还要把模板引用的版本号给改掉。

使用工具消灭重复劳动

如果我们使用用 webpack 为什么不用一个插件解决这些呢?但是,但是这儿有一个问题:
cdn 资源没规则,从 package.json 中完全看不出;

  1. 模块的依赖有可能已经打包在一起;如 react-router,将 依赖的小文件一起打包。
  2. 依赖不明确;如 bootstap 依赖 jquery 是在 dependencies 中指定的,而 react-router 其实只需要外部的 react,在 peerDependencies 中声明的。
  3. 现有的资源路径规则也不确定,如 bootcdn.cn 上 min.js 存在 -min.js 和 .min.js。

好吧,那我就自己维护一份,cdn-webpack-plugin 就是这个插件的雏形。为主流构建工具提供插件,也能够推动资源的共享。

理想与现实

理想如果实现了,那前端资源无需 npm install,直接引用 CDN 就可以了。另外我们还能够做一些优化:根据资源共同出现频率选择合适的资源 combo
如:react 全家桶 用到 redux 系列, redux react-redux react-thunk。

现实是,我们不可能维护所有资源的所有版本,不可能取代 npm 或 yarn。也不会如它们这么及时,一个第三方库 fix bug 升级,不大可能立即同步到 CDN 上。最大的问题还是第三方的资源不可信,除非几个大公司牵头组织一个第三方的资源库。