grunt构建工具:scss转css

发布于:2025-03-13 ⋅ 阅读:(20) ⋅ 点赞:(0)

Grunt 是一个基于 JavaScript 的任务运行工具,通常用于自动化重复性任务,例如代码编译、文件压缩、单元测试等。它通过配置文件 Gruntfile.js 来定义任务和插件。
完整项目地址:https://github.com/ylpxzx/grunt-scss-to-css

以下是 Grunt 的一些关键概念:

  1. Gruntfile.js: 这是 Grunt 的配置文件,用于定义任务和插件。它通常包含 module.exports 函数,里面有 grunt.initConfig 方法来初始化任务配置
  2. 任务 (Tasks): Grunt 的核心是任务。任务可以是单个任务,也可以是多个任务的组合。任务可以通过命令行运行,例如 grunt sass 或 grunt watch
  3. 插件 (Plugins): Grunt 有大量的插件,可以用来执行各种任务,例如编译 Sass、压缩 JavaScript 文件、运行单元测试等。插件可以通过 grunt.loadNpmTasks 方法加载
  4. 配置 (Configuration): 在 grunt.initConfig 方法中,定义了各个任务的配置。每个任务都有自己的配置选项,例如文件路径、选项等

用Grunt将scss文件转为css

初始化项目

  • 新建项目目录:grunt-scss-to-css

  • 在项目根目录执行以下命令进行项目初始化

    npm init
    

准备工作

  • 安装 grunt-cli

    npm install -g grunt-cli
    
  • 安装 ruby

    官方下载地址:https://rubyinstaller.org/downloads/archives/

    请添加图片描述

    安装完成后,打开 cmd, 运行"ruby -v" 看是否安装完成 (直接在 vscode 终端执行,好像会提示不存在 ruby 指令)

    在打开的项目根目录下执行下面命令,安装sass

    gem install sass
    
  • 安装构建项目所需的npm包

    npm install grunt
    # sass转css的包
    npm install grunt-contrib-sass
    # 监听文件变化后触发重新构建的包
    npm install grunt-contrib-watch
    
  • 在项目根目录下新建Gruntfile.js文件

项目结构如下:

请添加图片描述

构建逻辑编写

  • Gruntfile.js

    module.exports = function(grunt) {
    
      grunt.initConfig({    //初始化配置grunt任务
        sass: {
          dist: {
            files: {
              'dist/css/output.css': 'src/scss/index.scss'  // src/scss/index.scss文件编译后输出到dist/css/output.css文件
            }
          }
        },
        watch:{
          scripts:{
            files:["src/scss/*.scss"],  // 监控文件夹下的scss文件
            tasks:["sass"],  // 监控到文件变化后,执行sass任务
            options:{
              spawn: false
            }
          }
        },
      });
      
      grunt.loadNpmTasks('grunt-contrib-watch');   //加载watch监听插件任务
      grunt.loadNpmTasks('grunt-contrib-sass');   //加载sass插件任务
    
      grunt.registerTask('scsstocss', ['sass', 'watch']);  //新增一个注册任务test, 运行sass和watch任务
    };
    
  • 新增scss文件进行测试:src/scss/index.scss

    * {
    	border: 0;
    	box-sizing: border-box;
    	margin: 0;
    	padding: 0;
    }
    :root {
    	--hue: 223;
    	--bg: hsl(var(--hue),10%,90%);
    	--fg: hsl(var(--hue),10%,10%);
    	--primary: hsl(var(--hue),90%,30%);
    	--trans-dur: 0.3s;
    	--trans-timing: cubic-bezier(0.65,0,0.35,1);
    	font-size: calc(16px + (48 - 16) * (100vw - 280px) / (3840 - 280));
    }
    body,
    button {
    	font: 1em/1.5 "DM Sans", sans-serif;
    }
    body {
    	background-color: var(--bg);
    	color: var(--fg);
    	display: flex;
    	height: 100vh;
    }
    form {
    	container: form / inline-size;
    	margin: auto;
    	padding: 1.5em;
    	width: 100%;
    	max-width: 36em;
    }
    .btn {
    	background-color: var(--primary);
    	border-radius: 0.25em;
    	color: hsl(0,0%,100%);
    	cursor: pointer;
    	display: block;
    	padding: 0.375em 0.75em;
    	transition:
    		background-color var(--trans-dur) var(--trans-timing),
    		opacity var(--trans-dur) var(--trans-timing);
    	width: 100%;
    	-webkit-appearance: none;
    	appearance: none;
    	-webkit-tap-highlight-color: transparent;
    
    	&:disabled {
    		cursor: not-allowed;
    		opacity: 0.5;
    	}
    	&:not(:disabled):hover {
    		background: hsl(var(--hue),90%,10%);
    	}
    	&-group {
    		display: flex;
    		justify-content: center;
    		gap: 0.75em;
    		margin-top: 1.5em;
    	}
    }
    .steps {
    	// --trans-dur: 0.15s;
    	background-color: hsl(0,0%,100%);
    	border-radius: 0.75em;
    	display: flex;
    	padding: 1.5em;
    	flex-direction: column;
    	justify-content: center;
    	width: 100%;
    
    	&__connector,
    	&__step {
    		position: relative;
    	}
    	&__connector {
    		background-color: hsl(var(--hue),10%,80%);
    		margin-inline-start: 0.75em;
    		width: 0.125em;
    		height: 1.25em;
    		transform: translateX(-50%);
    		transition: background-color var(--trans-dur);
    
    		&:before {
    			background-color: var(--primary);
    			content: "";
    			display: block;
    			width: 100%;
    			height: 100%;
    			transform: scale(1,0);
    			transform-origin: 50% 0;
    			transition:
    				background-color var(--trans-dur),
    				transform var(--trans-dur) var(--trans-timing);
    		}
    	}
    	&__step {
    		display: flex;
    		align-items: center;
    		flex-shrink: 0;
    		z-index: 1;
    
    		&-name {
    			color: hsl(var(--hue),10%,50%);
    			font-size: 0.75em;
    			line-height: 2;
    			transition:
    				color var(--trans-dur) var(--trans-timing),
    				font-weight var(--trans-dur) var(--trans-timing);
    		}
    		&-number {
    			background-color: hsl(var(--hue),10%,80%);
    			color: hsl(0,0%,100%);
    			border-radius: 50%;
    			margin-inline-end: 0.5em;
    			text-align: center;
    			width: 1.5em;
    			height: 1.5em;
    			transition:
    				background-color var(--trans-dur) var(--trans-timing),
    				box-shadow var(--trans-dur) var(--trans-timing);
    		}
    		&--current &-name,
    		&--done &-name {
    			color: hsl(var(--hue),10%,10%);
    			font-weight: 700;
    		}
    		&--current &-number,
    		&--done &-number {
    			background-color: var(--primary);
    		}
    		&--current &-number,
    		&--current &-name {
    			transition-delay: var(--trans-dur);
    		}
    		&--current &-number {
    			box-shadow: 0 0 0 0.125em hsla(var(--hue),90%,30%,0.4);
    		}
    	}
    	&__step--done + &__connector {
    		&:before {
    			transform: scale(1,1);
    		}
    	}
    }
    
    /* Change layout depending on form width */
    @container form (min-width: 30em) {
    	.btn {
    		width: auto;
    	}
    	.steps {
    		flex-direction: row;
    		align-items: center;
    		padding: 1.5em 2.25em 2.25em 2.25em;
    
    		&__connector {
    			margin-inline-start: 0;
    			width: 100%;
    			height: 0.125em;
    			transform: translateY(-50%);
    
    			&:before {
    				transform: scale(0,1);
    				transform-origin: 0 50%;
    
    				[dir="rtl"] & {
    					transform-origin: 100% 50%;
    				}
    			}
    		}
    		&__step {
    			&-name {
    				position: absolute;
    				top: 100%;
    				left: 50%;
    				text-align: center;
    				width: 6em;
    				transform: translateX(-50%);
    			}
    			&-number {
    				margin-inline-end: 0;
    			}
    		}
    	}
    }
    
    /* Dark theme */
    @media (prefers-color-scheme: dark) {
    	:root {
    		--bg: hsl(var(--hue),10%,10%);
    		--fg: hsl(var(--hue),10%,90%);
    		--primary: hsl(var(--hue),90%,70%);
    	}
    	.btn {
    		color: hsl(var(--hue),10%,10%);
    
    		&:not(:disabled):hover {
    			background: hsl(var(--hue),90%,50%);
    		}
    	}
    	.steps {
    		background-color: hsl(var(--hue),10%,20%);
    
    		&__connector {
    			background-color: hsl(var(--hue),10%,40%);
    		}
    		&__step {
    			&-name {
    				color: hsl(var(--hue),10%,50%);
    			}
    			&-number {
    				background-color: hsl(var(--hue),10%,40%);
    				color: hsl(var(--hue),10%,20%);
    			}
    			&--current &-name,
    			&--done &-name {
    				color: hsl(var(--hue),10%,90%);
    			}
    			&--current &-number {
    				box-shadow: 0 0 0 0.125em hsla(var(--hue),90%,70%,0.4);
    			}
    		}
    	}
    }
    
  • 执行任务

    # 在项目根目录下运行该命令
    grunt scsstocss
    
  • 最终项目结构:.sass-cache、dist/css/…为构建后生成的文件

    请添加图片描述