webpack - 如何通过代码拆分在 Vue/Webpack webapp 中部分加载 Sass/样式表文件
问题描述
我正在为使用Vue 2 和 Webpack 3 构建的 Web 应用程序使用代码拆分技术。JS 块以异步方式运行良好,在 Lighthouse 性能审计中给了我一个很好的分数。
然而,通过打开 DevTools 上的“Coverage”选项卡,我可以看到大约 99% 的 CSS 样式在第一次内容绘制(即第一个页面加载)时没有使用。原因很简单:我的main.scss
文件(如下所示)导入了项目的所有样式表,创建了一大块渲染阻塞代码。我为 Sass 文件遵循了一个通用的、流行的设计模式,但显然它不适合 Vue 使用的基于组件的模式。
我试图从“.vue”单文件组件加载组件样式表,但我遇到了另一个问题:因为 WebpackApp.vue
在我导入我的主文件之前解析这些文件,所以main.scss
在整个代码中使用的所有 Sass 变量都去' undeclared',从而在整个地方抛出错误。
我的main.scss
文件看起来有点像这样:
//base style
@import 'base/variables';
@import 'base/fonts';
@import 'base/tools';
@import 'base/typography';
@import 'base/general';
@import 'base/buttons';
@import 'base/elements';
// ...
//components style
@import 'components/topnav';
@import 'components/header';
@import 'components/sidemenu';
@import 'components/footer';
@import 'components/login';
// ...
//responsiveness
@import 'base/responsiveness';
// cross browser styles
@import 'base/cross-browser';
有没有办法拆分这个大文件并相应地异步加载样式,只有在需要它们时,就像其他 JS 块一样?
我不相信有一些特殊的 Webpack 加载器/插件可以为我做到这一点,我正在寻找一种重构最少的解决方案。整个磨难将我的交互时间指标增加到大约 6-7 秒。
解决方案
所以:在一些失败和错误之后,在 vue-loader 的文档上找到这个页面后,我想我找到了一个合理的解决方案,分解如下:
- 确保拥有
sass-loader
并node-sass
安装 - 按照文档中的建议,在上面的链接中编辑常规 Webpack 配置。例如,为了包含 SASS 变量文件或您可能想要的任何其他通用样式表(main.scss...),您可以执行以下操作:
{
loader: 'sass-loader',
options: {
data: `path/to/_variables.scss`,
includePaths:[__dirname, 'src']
}
}
- 接下来,我分解了
main.scss
文件:只留下了基本样式的导入,例如 Sass 变量、字体、mixin、响应式样式、表单等。 - 我删除了
main.scss
文件的通常导入App.vue
,它自动删除了 app.js 块中巨大的 700 KB 负载。 - 最后,在每个路由/视图模板上,我添加了相应的组件样式表,形式如下:
<style lang="scss" scoped>
@import 'path/to/main.scss'; // **IF YOU HAVE `vue-cli` VERSION > 3.X, THEN YOU DON'T HAVE TO IMPORT GENERAL STYLE SHEETS SUCH AS THIS**
@import 'path/to/component/component.scss';
...
</style>
导入主样式表文件不是问题的原因是因为它是非阻塞代码,保持执行线程继续运行 - 与以前巨大的样式表阻塞线程并使页面空白太久时不同。显然,Vue 在其自己的 .vue 文件中对代码拆分的开箱即用支持使所有这些“合法”且超快。
结果?
初始页面加载(令人惊讶地)不到 1.5 秒(4.5-6),因为 Lighthouse 性能得分达到了 95-97 的稳定范围......在开发环境中,我什至没有启用 JS 或文本压缩!此前,比分是45-55左右。我期待在其他环境中部署它以获得更多统计信息,其中配置了更多调整,但它看起来确实是一个非常有前途的解决方案。
推荐阅读
- c - 为什么 AddressSanitizer 在 nginx 中不显示 heap-use-after-free
- python - 每次减少一个数字(健康),执行一个代码
- excel - 使用 VBA 在 Excel 中修剪 100 万行的最快方法是什么?
- matlab - 非线性函数与实验数据的拟合方法
- ffmpeg - 可以使用 FFmpeg 在线流式传输给定的窗口吗?
- android - 当适配器开始侦听时,NestedScrollview 中的 RecyclerView 冻结
- python - 如何为索引列设置标签?
- python - 在 __post_init__ 中更改类型的数据类属性的类型提示
- r - 如何将特定因子水平删除为 r 中的缺失值?
- flutter - 如何在flutter-web中将触摸事件监听器标记为被动?