.net 项目静态文件自动压缩打包
打包工具选型
在 ASP.NET MVC 时代,我们常使用 BundleCollection 设置需要打包压缩的 js 和 css 文件,运行时框架会自动处理打包压缩过程并将最终结果传入响应。
ASP.NET Core 开始,不再提供内置的打包压缩组件,官方推荐 WebOptimizer 替代使用。
上述两者都是在运行时实时处理,应该至少在系统初始化时会占用一定的资源。
时间来到 .NET 大一统时代,截止目前(.NET7),我们仍然只能寻求外部组件的帮助。有一个编译期生成预期文件的组件 BuildBundlerMinifier,nuget 安装后进行简单的 JSON 配置即可使用,但遗憾的是,它不支持压缩包含 ES6 语法的 js,会报未将对象引用设置到对象的实例错误。
于是我们开始考虑独立于 .NET 平台的,较为成熟的方案,比如 grunt 和 gulp。
grunt: 使用 JSON 描述构建步骤gulp:基于流传递(管道机制)
这两者都拥有丰富的插件,以应对各种需求。下面以更年轻更简单的 gulp 为例,说明如何使之与 Visual Studio 配合使用。
示例
假设有如下 .NET 项目,其中按约定静态文件存放在 wwwroot 目录下

安装 gulp
# 全局安装 gulp 或 gulp-cli,提供可在命令行执行的 gulp 指令
npm install -g gulp-cli
需要注意的是,我们还需要在待处理的目录下安装 gulp,否则后续运行命令时会提示 Local gulp not found. 错误。其实这是Gulp故意设计的,原因是为了版本和依赖的控制,也就是当别人 fork 你的代码,或者你过段时间拷贝到别的电脑上再 gulp 的时候,能控制该项目中 gulp 的版本和其他插件的版本始终保持不变。(这里的 gulp 其实也可看作插件,只是它是官方提供的。博主不怀疑 gulp 团队前向兼容的能力,推测是考虑第三方插件前向兼容的能力参差不齐的缘故。)
# 进入待处理的目录,此是 .net 项目下的一个子目录
cd wwwroot/
# 将此子目录初始化为 npm 项目
npm init -y
# 安装 gulp 插件,提供各种 gulp.xxx()
npm install gulp -D
此时在该目录下查看 gulp 版本
gulp --version
# 输出:
CLI version: 2.3.0 # 全局 cli 版本
Local version: 4.0.2 # 当前项目下 gulp 插件版本
安装需要的第三方插件
# 以下各插件功能请查阅相关资料
npm i -D gulp-cssmin gulp-autoprefixer gulp-uglify
# es6 语法转 es5,窃以为目前浏览器对 es6 的支持程度,大可不必
npm i -D gulp-babel @babel/core @babel/preset-env
# 提供合并若干文件为单一文件的功能
npm i -D gulp-concat
编写 gulpfile.js
在项目根目录下(wwwroot/)新建 gulpfile.js,编写任务脚本
// 加载 项目gulp 依赖包
const gulp = require('gulp');
// 加载 css相关依赖包
const autoprefixer = require('gulp-autoprefixer');
const cssmin = require('gulp-cssmin');
// 加载 js相关依赖包
const uglify = require('gulp-uglify');
const babel = require('gulp-babel');
// 加载文件合并处理包
const concat = require('gulp-concat');
// 打包 css
const cssHandler = function () {
return gulp.src('./css/main.css')
.pipe(autoprefixer())
.pipe(cssmin())
.pipe(concat('main.min.css'))
.pipe(gulp.dest('./css'))
}
// 打包 js
const jsHandler = function () {
return gulp.src(['./js/instruction/*.js', './js/repos/*.js', './js/app/*.js'])
.pipe(babel({ presets: ['@babel/env'] }))
.pipe(uglify())
.pipe(concat('main.min.js'))
.pipe(gulp.dest('./js'))
}
// 3-3,定义默认执行程序
module.exports.default = gulp.parallel(cssHandler, jsHandler)
注意,gulp.dest() 参数表示的是目标目录而非目标文件名(输出文件名默认同源文件名),如果要自定义输出文件名可使用 gulp-rename 插件;或如上使用 gulp-concat,它的目的是合并若干文件为单一文件,自然能指定生成的文件名咯。
完成上述步骤后,我们就可以在命令行执行 gulp 检查输出结果。
编译 .net 项目时自动打包
在 .net 项目根目录下(注意非 wwwroot/)新建一个批处理文件 package-statics.bat:
cd wwwroot
gulp
然后编辑项目文件(.csproj),在 节点下加入如下配置:
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Command="call package-statics.bat" />
</Target>
意思很简单:在编译前先执行批处理文件,也就是先执行之前我们设置好的 gulp 流程。
如果你的项目采用了 CI/CD 自动构建,可能服务器上并没有安装 gulp,那么可以在本地先执行打包,将生成后的文件提交,然后在服务器上编译时跳过打包步骤,直接使用提交的文件。实现这个场景也很简单,只要在上述 节点内配置执行条件即可:<Target ... Condition="'$(Configuration)'=='DEBUG'">。参看演练:使用 MSBuild
ps:在页面中,我们希望开发时依然引用的是原文件,上线后才引用打包后文件,那么可以使用 <environment> 标记,通过判断环境变量达到这一目的:
<environment include="Development">
<link ... href="~/css/main.css" />
</environment>
<environment include="Production">
<link ... href="~/css/main.min.css" />
</environment>
参考资料
.net 项目静态文件自动压缩打包的更多相关文章
- gulp自动化打包及静态文件自动添加版本号
前端自动化打包发布已是一种常态,尤其在移动端,测试过程中静态资源的缓存是件很头疼的事情,有时候明明处理的bug测试还是存在,其实就是缓存惹的祸,手机不比pc浏览器,清理缓存还是有点麻烦的.所以自动化实 ...
- Grunt针对静态文件的压缩,版本控制打包方案
在讲之前先谈谈大致步骤:安装nodejs -> 全局安装grunt -> 项目创建package.json --> 项目安装grunt以及grunt插件 -> 配置Gruntf ...
- IDEA springboot 项目静态文件修改不更新的问题
springboot 项目的页面和静态文件,在项目启动后,修改无效.按照下面的配置可以解决问题. 1.file-setting 勾选项目自动构建 2.使用快捷键 ctrl+ shift+ alt + ...
- Django项目静态文件加载失败问题
在我们平时的开发过程中,为了方便调试程序,我们都是打开开发者模式,即Debug=True,当我们正式上线的时候肯定就需要把开发者模式关掉,用uwsgi部署上去以后,突然发现我们平时辛苦做的项目的静态文 ...
- winRAR将单独文件分别压缩打包
2014-4-7 首先选中多个需要打包的文件,右键-->添加到压缩文件-->选中"文件"选项卡-->勾选下面的"把每个文件压缩到单独文件中. 如下图所示
- [转]C#如何把文件夹压缩打包然后下载
public partial class _Default2 : System.Web.UI.Page{ protected void Page_Load(object sender, EventAr ...
- idea使用Maven创建的JavaWeb项目新建文件时没有打包到target目录报错
背景:在使用tomcat发布这个项目时,浏览网页,js没有效果. 问题:发现打包之后没有同步到target里 解决办法:点击最右侧的Maven栏->所建项目->Lifecycle-> ...
- java/resteasy批量下载存储在阿里云OSS上的文件,并打包压缩
现在需要从oss上面批量下载文件并压缩打包,搜了很多相关博客,均是缺胳膊少腿,要么是和官网说法不一,要么就压缩包工具类不给出 官方API https://help.aliyun.com/documen ...
- Linux文件压缩/打包/解压
在Linux日常维护中,经常需要备份同步一些比较重要的文件,而在传输过程中如果文件比较大往往会非常慢,而且还会非常占用空间,这时候就需要我们使用压缩工具对大文件进行压缩打包,下面我们来介绍一下常用的压 ...
- webpack4.16压缩打包
webpack4.16压缩打包 本文所用插件版本如下: nodejs:v8.11.3; npm:5.6.0 webpack:4.16 webpack的更新速度很快,差不多几个月就会出一版,最新的4系列 ...
随机推荐
- Centos7.9中使用Docker安装云崽机器人
Centos7.9中使用Docker安装云崽机器人 前面我写了如何普通版搭建云崽教程,今天我们来使用docker来安装,感谢docker镜像源作者:如青桑(QQ: 1666633887) 普通版教程: ...
- Chronicle Pro - 一款简单 Mac 理财规划师,管理你的的个人预算
使用Chronicle追踪和支付账单,管理你的个人预算,这是一款简单的Mac理财规划师.获得通知,这样你就不会错过下一个付款截止日期;你再也不用付滞纳金了.把你所有的账单放在一起,计划.检查和分析它们 ...
- 汽车制造工艺 2.5D 可视化组态监控 | 图扑软件
前言 随着世界经济的不断发展,汽车作为一个如今随处可见的物体,从大体上概括是由四大部分组成:发动机.底盘.车身.电气系统.看似简单的几个名词组件,其内部却是由无数的细小零件构成,一辆汽车更是由上万个微 ...
- java代码审计-CSRF
0x01 前言 CSRF跨站请求伪造(Cross-site request forgery),当某个接口没有设置CSRF验证,点击了别人恶意的链接,可能会造成对这个接口发送相应的数据,造成某个数据被更 ...
- 手把手带你从0完成医疗行业影像图像检测三大经典模型InceptionV3-RestNet50-VGG16(附python源代码及数据库)——改变世界经典人工智能项目实战(一)手把手教学迁移学习
目录 1.迁移学习简介 2.项目简介 3.糖尿病视网膜病变数据集 4.考虑类别不平衡问题 5.定义模型质量 6.定义损失函数 7.预处理图像 8.搭建迁移学习网络 VGG16 迁移学习网络 Incep ...
- window计时器函数
// 定时器: // 计时器 // 开启:setInterval() // 参数1:回调函数 // 参数2:毫秒数 // 功能:每个指定的毫秒数执行一次回调函数 demo: var t = setIn ...
- react组件之非受控组件和高阶组件
非受控组件 受控组件和非受控组件的区别 ----- value import React, { Component } from 'react' export default class extend ...
- Thanos工作原理及组件简介
Thanos 简介 Thanos 是一个「开源的,高可用的 Prometheus 系统,具有长期存储能力」.很多知名公司都在使用 Thanos,也是 CNCF 孵化项目的一部分. Thanos 的一个 ...
- Java设计模式 —— 工厂模式
3 简单工厂模式 3.1 创建型模式 Creational Pattern 关注对象的创建过程,对类的实例化过程进行了抽象,将软件模块中对象的创建和对象的使用分离,对用户隐藏了类的实例的创建细节.创建 ...
- visio秘钥
一.Visio2016专业版永久激活码: Visio 2016 Professional Retail零售版 [Key]:NKVJM-8MTT4-8YDFR-6738M-DPFJH [Key]:W9W ...