如何编译站点/页面实际使用的SCSS为外部或内部CSS?
我常用Next.js(自动编译外部SCSS为CSS)或静态/CMS站点(用Gulp编译SCSS)搭建网站,但这种方式下所有页面都会加载完整的CSS,哪怕很多样式根本没用到,徒增页面体积。
我自己做了个基础框架,里面有大量移动端优先的响应式隐藏样式:
.hide { display: none; } @media (min-width: $vsmall) { .hide-vsmall { display: none; } } @media (min-width: $small) { .hide-small { display: none; } } @media (min-width: $medium) { .hide-medium { display: none; } } @media (min-width: $large) { .hide-large { display: none; } } @media (min-width: $vlarge) { .hide-vlarge { display: none; } }
比如在某页面用.hide-medium类来在中等断点及以上隐藏内容:
<div class="hide-medium">My content</div>
但这类样式会全部编译进外部CSS,哪怕只有单个页面用到其中一个,其他页面完全不用。
以前习惯用外部样式表,觉得内部、内联CSS不好,但现在不确定是否有变化,如果内部CSS可行我愿意切换。但就算切换,也需要解决如何把基础SCSS里用到的样式提取到页面内部CSS的问题。尽量不想用内联样式,但如果操作简单可行也能接受。
我自制框架是因为只包含可能用到的类,用Bootstrap这类框架的话基础CSS体积会大很多,但不确定现在Bootstrap有没有改进。
想咨询:有没有办法只把站点全局用到的SCSS编译成外部文件,或者为每个页面生成仅包含用到的样式的内部CSS(如果内部CSS现在是可行方案的话)?
一、Next.js 按需编译方案
使用CSS Modules
把基础SCSS拆分成模块文件(比如utils.module.scss),在需要用到特定隐藏类的页面组件里,仅导入对应类:import styles from '../styles/utils.module.scss'; <div className={styles['hide-medium']}>My content</div>Next.js会自动做Tree Shaking,只将当前组件用到的类编译进页面CSS,未使用的类不会被打包。
自定义工具类按需生成
参考Tailwind的按需生成逻辑,用postcss插件配合自定义配置,让工具类仅在被页面引用时生成。如果是自制小框架,直接用CSS Modules更简洁。
二、Gulp 静态站点按需编译方案
集成PurgeCSS
在Gulp编译流程中加入PurgeCSS插件,它会扫描HTML/模板文件,识别实际用到的类,删除编译后CSS中未使用的样式。配置示例:const gulp = require('gulp'); const sass = require('gulp-sass')(require('sass')); const purgecss = require('gulp-purgecss'); gulp.task('sass', function() { return gulp.src('src/scss/**/*.scss') .pipe(sass().on('error', sass.logError)) .pipe(purgecss({ content: ['src/**/*.html', 'src/**/*.js'], // 扫描所有页面文件 safelist: { standard: [/^hide-/] // 若需保留所有hide前缀类(防止动态生成的类被误删),可添加此规则 } })) .pipe(gulp.dest('dist/css')); });编译后的CSS只会包含页面实际用到的hide类,多余样式会被清除。
拆分全局与页面级CSS
把全局通用样式(如重置样式、基础排版)单独编译为global.css,每个页面的专属工具类(如用到的hide类)单独写在对应页面的SCSS文件中,Gulp分别编译后,页面仅加载全局CSS+自身专属CSS。
三、内部/内联CSS的可行性
现在内部CSS(页面<style>标签中的样式)完全可行,尤其是单页或小站点场景,不会有过去的维护性问题,还能减少HTTP请求。结合上述按需编译方案,内部CSS可自动生成:
- Next.js中用
next/head组件在页面内嵌入样式,配合CSS Modules提取用到的类注入。 - Gulp可通过插件把页面专属样式直接注入HTML的
<head>中。
内联样式适合单个元素的特殊样式,但对于响应式hide这类工具类,用类的方式更灵活,不推荐大量使用。
四、Bootstrap 现状
Bootstrap 5支持按需导入组件和工具类,通过@import单独引入所需部分,比如仅导入响应式工具类:
@import "bootstrap/scss/functions"; @import "bootstrap/scss/variables"; @import "bootstrap/scss/mixins"; @import "bootstrap/scss/utilities";
打包后的体积会比全量引入小很多,但如果自制框架已足够精简,还是用自制框架更轻量。
内容的提问来源于stack exchange,提问作者Laurence Cope

