• vue项目发布采用gzip压缩文件部署到nginx无法运行问题


    gzip压缩分为服务器压缩和前端文件压缩。应该二者结合,综合使用。

    一、问题描述

    有一个VUE项目,开发环境下,使用npm运行,一切正常,发布部署到nginx上一片空白。用谷歌浏览器进入开发者工具,提示什么“Uncaught SyntaxError: Unexpected token ‘<’ ”
    在这里插入图片描述
    为什么会报这个错误呢?这与nginx的设置有关。

    location / {
    	root   E:/订餐谁拿饭抓阄评估规划执行监控审计管理系统/code/web/dist;		
    	index  index.html index.htm;
    	try_files $uri $uri/ /index.html;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    最后这一句,当出错的时候会强制跳转到 index.html 页面,而js文件不能识别html,因此报Uncaught SyntaxError: Unexpected token < 错误。

    更确切地说,是浏览器向服务器请求js文件,服务器报错了,依照nginx的设定,转跳到了index.html,即nginx向客户端返回了index.html的内容。而浏览器接收到这部分"javascript"内容后,无法解释,于是就报了“Uncaught SyntaxError: Unexpected token <”的错。

    为什么向服务器请求js文件会报错呢?原因是,在我们的发布包里,没有这些js文件,只有js文件的压缩包:
    在这里插入图片描述
    nginx应该是可以识别这些压缩包,能处理gzip,所以没有报404错误(如果将发布包部署到IIS,会报404错误),但不知道什么原因,nginx没有正确返回js内容,而是触发了异常。

    二、vue的文件压缩处理

    之所以我这个vue项目的发布文件,有*.gz文件,是因为配置文件vue.config.js中指定使用了压缩插件:

    switch (process.env.NODE_ENV) {
      case "development":
    	...
        break;
      case "production"://vue3默认情况下,npm run build时,process.env.NODE_ENV==="production"
      	...
        WEBPACK_PLUGINS.push(
          new CompressionWebpackPlugin({
            filename: "[path].gz[query]",
            algorithm: "gzip",
            test: new RegExp("\\.(" + productionGzipExtensions.join("|") + ")$"),
            threshold: 10240,
            minRatio: 0.8,
            deleteOriginalAssets: true,//删除压缩后的原文件
          })
        );
        break;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    三、nginx的gzip设置

    事实上,对于服务器来说,有2种应用gzip的途径。一是我们发布文件的时候,不做任何处理,由nginx在处理客户端请求时,将内容压缩返回;二就是我们发布压缩文件,nginx直接读取并返回给客户端。

    两种方案,nginx的设置有所不同。

    1、nginx压缩

    http {
        include       mime.types;
        default_type  application/octet-stream;	
        sendfile        on;
    
    	server {
    	    listen       8001;
            server_name  localhost;
    
            gzip on;
            gzip_min_length 1k;
            gzip_buffers 4 16k;
            #gzip_http_version 1.0;
            gzip_comp_level 8;
            gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
            gzip_proxied any;
            gzip_vary off;
            gzip_disable "MSIE [1-6]\.";
    
    		location / {
    			root   E:/订餐谁拿饭抓阄评估规划执行监控审计管理系统/code/web/dist;		
    			index  index.html index.htm;
    			try_files $uri $uri/ /index.html;
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    使用浏览器观察,可以看到
    在这里插入图片描述

    2、发布文件压缩

    http {
        include       mime.types;
        default_type  application/octet-stream;	
        sendfile        on;
    
    	server {
    	    listen       8001;
            server_name  localhost;
    
    		#会优先查找静态gzip资源
    		gzip_static on;
    		
    		location / {
    			root   E:/订餐谁拿饭抓阄评估规划执行监控审计管理系统/code/web/dist;		
    			index  index.html index.htm;
    			try_files $uri $uri/ /index.html;
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    我的情况,就属于第二种方案,然而却出现了问题。出现问题的原因,是应该保留压缩前的原文件,而不是删掉。即部署时,被压缩文件既有压缩包,又有原文件。nginx会有限查找静态gzip资源。要保留原文件的原因,是nginx用来索引和对照的?
    在这里插入图片描述
    使用浏览器观察,
    在这里插入图片描述
    注意方案1的ETag存在"W/"开头,而方案2的ETag则没有。‘W/’(区分大小写)表示使用弱验证器 。弱 etags 很容易生成,但在比较时用处不大。强验证器是比较的理想选择,但很难有效地生成。ETag弱相同,表示两个资源可能在语义上是等效的,但不是逐字节相同的。这意味着当使用字节范围请求时,弱 ETag 会阻止缓存,但强 ETag 意味着范围请求仍然可以被缓存。

    3、两种压缩方案的对比
    对比第一种和第二种方式,发现请求ETag有区别,第二种应该比较好。避免前端没有做压缩处理,服务端最好兼容两种都配置,存在静态gzip则用静态资源,不存在则服务端处理。

    四、解决方案

    综上,解决方案很简单,就是我们在发布的时候,既要压缩,又要保留压缩前的文件,即将deleteOriginalAssets的值设为false。

    vue.config.js

    WEBPACK_PLUGINS.push(
          new CompressionWebpackPlugin({
            filename: "[path].gz[query]",
            algorithm: "gzip",
            test: new RegExp("\\.(" + productionGzipExtensions.join("|") + ")$"),
            threshold: 10240,
            minRatio: 0.8,
            deleteOriginalAssets: false,//删除压缩后的原文件
          })
        );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    nginx采用方案2或者结合起来使用均可。

    参考文章:
    Vue 项目性能优化之gzip

  • 相关阅读:
    有意识的神经网络之对比网络层和后意识层
    并发编程中的锁、条件变量和信号量
    Linux内存管理(二十一):LRU 第二次机会法
    vue无感刷新
    redis应用于微服务缓存的探讨
    文件真实类型识别 - linux c file
    【VMware vSphere】搭建属于自己的 vSphere 实验环境(2)——FreeNA的安装与初始化配置
    Java实现加密(一)AES加解密
    【yolov5】原理详解
    vins-course运行
  • 原文地址:https://blog.csdn.net/leftfist/article/details/125614805