Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >从Highlight浅谈Webpack按需加载

从Highlight浅谈Webpack按需加载

作者头像
MrTreasure
发布于 2018-08-09 08:52:11
发布于 2018-08-09 08:52:11
2K00
代码可运行
举报
文章被收录于专栏:不止是前端不止是前端
运行总次数:0
代码可运行

动态加载CSS.gif

前言

最近有在使用 highlight.js 做代码的高亮展示,主要是展示对 SQL 语言的处理。看了看 highlight.js 的提供的相关代码

![2.png](https://upload-images.jianshu.io/upload_images/3995692-dc52856084af134e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

因为只需要加载对应语言的种类,以及一种样式,所以我们希望 webpack 能够按需加载

按需加载的实践

完全加载

为了对比出按需加载究竟能帮助我们节约多少资源,我们先贴出没有按需加载的代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 忽略一些无关的代码
import * as hljs from 'highlight.js/lib/highlight'
import 'highlight.js/styles/atom-one-light.css'

export class Highlight extends React.Component {

  public componentDidMount() {
    hljs.highlightBlock((this.code as any))
  }

  public render() {
    return (
      <pre ref={ref => this.code = ref} style={{marginTop: 20}}>
        <code>{this.props.content}</code>
      </pre>
    )
  }
}

这是一份完整的加载,我们看看最后的数据有多大(包含完整引用的 antd 文件,我在项目中使用了 antd )

highlight-1.png

按需加载

接着我们按照官方的 demo 实现按需加载

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import * as hljs from 'highlight.js/lib/highlight'
import * as javascript from 'highlight.js/lib/languages/javascript'
hljs.registerLanguage('javascript', javascript)

其他的部分和上文相同,区别在于,没有从整个 highlight 中加载,而是引用了部分文件以及需要注册的 javascript 语言部分,默认是加载包含所有语言版本的 hljs ,看看这下的打包大小

highlight-2.png

我们可以看到,使用按需加载将近节省了600KB的空间,而使用按需加载的引入方式是 import * as XXX from 'module/lib/xxx'。并且使用 import { xx } from 'moduls' 并不能触发 webpack 的 treeshake,webpack仍然会打包完整库,哪怕引用的仅仅是从库里导出的接口(在ECharts下是如此表现的)。我们看看按需引用 antd 里的组件会是什么情况

部分按需引用

上面1.78MB的打包体积是 import { Card } from 'antd'(如gif效果图,我用Card包裹了高亮组件),接着我们看看

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import Card from 'antd/lib/card'

这种方式最后的打包体积

highlight-4.png

妈耶,居然这么小。

小结

  1. 如果要实现按需加载得使用babel-plugin-import,这个在TS下的情况还没有检查过
  2. 使用TS时,因为某些库的 d.ts 文件 指向的路径是模块,因此要导入该库的接口只能完整的导入该模块,比如ECharts,这个问题目前暂时还未解决

动态加载的实践

上面只是按需加载部分的JS,并且通过字符串写死的方式指定了路径,还有一部分,如同CSS的部分需要在组件生成时动态加载,或者通过变量的形式加载。如下所示

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  constructor(props) {
    super(props)
    require('highlight.js/styles/' + this.props.css)
  }

  static async getDerivedStateFromProps(nextProps) {
    // const css = await import('highlight.js/styles/' + nextProps.css)
    const css = require('highlight.js/styles/' + nextProps.css)
    console.log(css)
    return null
  }

我们在构造阶段通过props传过来的变量加载对应的CSS文件,之前是使用import 'highlight.js/styles/atom-one-light.css'的方式,我们看看两者打包体积的区别

highlight-css-1.png

highlight-css-2.png

通过指定加载的CSS体积大小是427KB,而动态加载的体积大小是484KB。动态加载的体积要比静态加载的体积大很多。分析一下webpack打包的行为

webpack始终结合关键字并按照静态地址信息进行打包。比如require('highlight.js/styles/' + nextProps.css) require是关键字,接下来 webpack 会对 require 这个函数中的入参进行分析,它会发现入参有两个部分构成, 一部分是硬编码的 'highlight.js/styles/' 另一部分是不可知的变量。webpack将会以硬编码部分为打包入口,将'highlight.js/styles/*'下所有文件打包,在运行时根据完整的路径记载资源。

所以我们没办法使用完全的变量 require(variable),因为这样webpack找不到打包的路径。

缺陷

效果图虽然能看到我们通过 Select 的选择按需加载 CSS 样式,但其实是有缺陷的,表现为右侧可以看到,动态加载的CSS是通过一个个style标签加载上去的,这样后面的样式效果会覆盖前面的。表现为 当 Select 又选到已经加载的样式时, 浏览器并不会重新加载那段代码,导致样式无效。这个问题在另一个组件中得到了解决 react-syntax-highlighter

还没来得及看具体的实现,不过我估计应该是使用了 CSS-MODULES,明天再看看

没来得及验证的部分

有注意到 我在使用 const css = await import('xxx'),const css = require('xxx'),这两者的表现上是有区别的,前者是一个Promise对象,后者直接返回了值,这就涉及到了一个同步和异步的问题,虽然最后打印出来都是 {}, 不过这是因为没有使用CSS modules的原因。以后再研究研究 import require 动态加载时的区别

总结

  1. import { Card } from 'antd'并不会触发按需加载,仍然会加载全部antd文件,应该使用import Card from 'antd/lib/Card'
  2. 使用变量加载require('highlight.js/styles/' + this.props.style) webpack会打包 'highlight.js/styles/*'下所有文件
  3. 猜想 在TS下即使只从某个库里引用接口, import { IXxx } from 'xxx',webpack仍然会打包所有的 'xxx' 文件(在ECharts的表现下如此)

以上都是我瞎编的

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.08.03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
关于VUE前端项目的优化
今天终于得空了,我要把 kui 说明文档这个项目优化下。打开太慢了,就是这个 http://k-ui.cn
chuchur
2022/10/25
4320
关于VUE前端项目的优化
vue.config.js的优化配置(element-ui, echarts, lodash按需加载 )
“关注 前端开发社区 ,回复“ 1” 即可加入 前端技术交流群,回复 “ 2” 即可免费领取500G前端干货!
前端老道
2020/09/11
8.4K0
vue.config.js的优化配置(element-ui, echarts, lodash按需加载 )
React第三方组件1(路由管理之Router的使用⑤按需加载-下)
本教程总共6篇,每日更新一篇,请关注我们!你可以进入历史消息查看以往文章,也敬请期待我们的新文章! 1、React第三方组件1(路由管理之Router的使用①简单使用)---2018.01.22 2、React第三方组件1(路由管理之Router的使用②多层级跳转及重定向)---2018.01.23 3、React第三方组件1(路由管理之Router的使用③传参)---2018.01.24 4、React第三方组件1(路由管理之Router的使用④按需加载-上)---2018.01.25 5、React第
前端人人
2018/04/11
2K1
React第三方组件1(路由管理之Router的使用⑤按需加载-下)
webpack4大结局:加入腾讯IM配置策略,实现前端工程化环境极致优化
在此对webpack的性能优化进行几点声明: 在部分极度复杂的环境下,需要双package.json文件,即实行三次打包 在代码分割时,低于18K的文件没必要单独打包成一个chunk,http请求次数过多反而影响性能 prerender和PWA互斥,这个问题暂时没有解决 babel缓存编译缓存的是索引,即hash值,非常吃内存,每次开发完记得清理内存 babel-polyfill按需加载在某些非常复杂的场景下比较适合 prefetch,preload对首屏优化提升是明显 代码分割不管什么技术栈,一
Peter谭金杰
2019/08/02
2.1K0
结合自己造的轮子实践按需加载
经过测试,发现两种方式打包后的体积都为 21 k,第二种方式仍然将整个包引入项目中了。可是 lodash 就是这么玩的呀,这和说好的不一样呀,难道是忽视了什么细节么。
牧云云
2018/09/19
8540
结合自己造的轮子实践按需加载
前端工程化之Webpack优化
好久没更文了,其实这段时间,一直没闲着。在准备一些比较重要的东西。忙着跑步,忙着学习,忙着xx。 总之就是,一直在忙着,从未停歇。
前端柒八九
2022/09/16
1.1K2
前端高级进阶:如何更好地优化打包资源
这是山月关于高级前端进阶暨前端工程系列文章的第 M 篇文章 (M 随便打的,毕竟也不知道能写多少篇),关于前 M-1 篇文章,可以从我的 github repo shfshanyue/blog[1] 中找到,如果点进去的话可以捎带~点个赞~,如果没有点进去的话,那就给这篇文章点个赞。。今天的文章开始了
winty
2020/03/02
1.6K0
highlight.js 在 Vue 中使用的一点儿经验
使用 markdown 来给程序写文档是非常方便的,自从用顺了 markdown 之后,都很久没打开过 Word 了。 既然是程序的文档,少不了需要插入一些示例代码,而对代码进行语法高亮渲染并配以合适的颜色主题,会让文档显得更炫,也更便于阅读。 要实现文档代码高亮渲染其实并不难。 实现方法 首先,把 markdown 文件加载为 vue 组件,这需要一个合适的 loader,自己目前使用 vue-markdown-loader。webpack 配置的 module.rules 中进行如下配置: {
overtrue
2018/07/05
2.4K0
第四章:高级特性与最佳实践 - 第三节 - Tailwind CSS 性能优化策略
在使用 Tailwind CSS 开发大型项目时,性能优化是一个不可忽视的话题。本节将从构建性能、运行时性能、文件体积等多个维度,详细介绍 Tailwind CSS 的性能优化策略。
程序猿梦工厂
2025/03/13
730
第四章:高级特性与最佳实践 - 第三节 - Tailwind CSS 性能优化策略
vue项目实现路由按需加载(路由懒加载)的3种方式
异步加载 vue-router配置路由 , 使用vue的异步组件技术 , 可以实现按需加载 . 但是,这种情况下一个组件生成一个js文件
Laikee
2022/04/25
1.7K0
百度Echarts图表在Vue项目的完整引入以及按需加载
近日在项目中需要进行图表展示,百度的Echarts图表是非常合适的一个选择。项目是vue-cli搭建的,如何在项目中引入Echarts就是一个问题了。亲自动手实践了下,整理总结,希望对小伙伴提供一些帮助,少踩一些坑。
胡哥有话说
2019/07/25
4.5K0
百度Echarts图表在Vue项目的完整引入以及按需加载
《前端那些事》聊聊前端的按需加载
前沿:按需加载是性能优化其中的一个环节,可以是图片的按需加载,也就是lazyload来实现按需加载的场景,也可以是组件库的引入,只需部分组件的使用而无需全局引入整个组件库的场景,又可以是路由的按需加载,当路由被访问的时候才加载对应组件的场景,以此来实现更高效率的使用等等,本文把“懒加载”也划分为按需加载
树酱
2020/07/03
2.5K0
《前端那些事》聊聊前端的按需加载
react-router4的按需加载实践(基于create-react-app和Bundle组件)
传送门:https://blog.csdn.net/foralienzhou/article/details/73437057
全栈程序员站长
2022/07/21
3310
改变渲染顺序实现按需加载,主要可以从以下几个方面入手:
当你访问http://localhost:3000/app/list/testpage时,Next.js 的处理顺序是:
用户1232103
2024/12/14
980
前端性能优化篇一:webpack性能优化
当我们不用cli,而是自己搭建项目架子的时候,会用到webpack构建我们的项目,在用webpack构建项目的时候,过长的打包编译时间和庞大冗余的代码会让我们感到头疼。所以优化webpack性能成为了不可或缺的一部分。下面我们一起来探讨webpack性能优化细节。
用户6835371
2021/06/01
2.2K0
前端性能优化篇一:webpack性能优化
在线网站 blog-react 项目的文档说明
此 blog 项目是基于 react 全家桶 + Ant Design 的,项目已经开源,项目地址在 github 上。
夜尽天明
2019/11/13
9500
在线网站 blog-react 项目的文档说明
Webpack的异步加载原理及分包策略(深度好文,建议收藏)
webpack ensure 有人称它为异步加载,也有人称为代码切割,他其实就是将 js 模块给独立导出一个.js 文件,然后使用这个模块的时候,再创建一个 script 对象,加入到 document.head 对象中,浏览器会自动帮我们发起请求,去请求这个 js 文件,然后写个回调函数,让请求到的 js 文件做一些业务操作。
winty
2020/12/07
4.7K0
Webpack的异步加载原理及分包策略(深度好文,建议收藏)
写给前端新人:从 0到1 搭建一个前端项目,都需要做什么?
本案例使用脚手架 create-react-app 初始化了项目。此脚手架有利有弊吧,项目目录结构简洁,不需要太关心 webpack 令人头疼的配置;弊端在于,脚手架确实有些庞大,构建时间在 4mins 左右。各位看官择优选择吧,也可以完全自己搭建一个项目。
zz_jesse
2021/06/01
5.3K0
React + TS + Ant Design 裁包小记
前段时间做了一个项目,是使用 Create-React-App 脚手架 + TypeScript + Ant Design 组件库搭建的,在减少包体积上有一些方法和大家分享一下。我们目标是将包体积降到几十 k 这样一个级别上,不受限于包体积,坦然使用框架。
iPlus26
2018/07/18
3.6K0
React + TS + Ant Design 裁包小记
浅谈低代码平台远程组件加载方案
低代码开发平台(LCDP)是无需编码(0代码)或通过少量代码就可以快速生成应用程序的开发平台。通过可视化进行应用程序开发的方法,使具有不同经验水平的开发人员可以通过图形化的用户界面,使用拖拽组件和模型驱动的逻辑来创建网页和移动应用程序。这两年越来越多的公司和开发人员开始自研低代码平台来达到降本提效的目的。今天和大家分享一下低代码平台开发过程中遇的一个问题和对应的解决思路。
CRMEB商城源码
2022/08/03
2.5K1
推荐阅读
相关推荐
关于VUE前端项目的优化
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验