Vue前端项目增量更新
Vue前端项目打包时会将项目页面代码封装成一个个的js和css,命名规则为chunk+哈希值。
当页面代码有变动并重新打包时,webpack只会更新有变动的文件,并更新文件名称里的哈希值,其他的文件并不会更新,根据这一特性,可以实现vue前端项目增量更新。
操作步骤如下:
1、 上一版本的打包文件命名为dist1,并重新打包前端项目(生成文件默认为dist)。如图
将执行程序拷贝到前端项目根目录下
点击空白处右键+shift,选择“在此处打开powershell窗口”,或者cmd进到上图中项目根目录下,执行命令“python compare.py ”,如图
3、 执行命令后会在当前目录下生成distAdd文件夹和distDel.txt
distAdd文件夹按原有目录结构存放有变动的文件
distDel.txt保存了原有的变更文件名称和路径
4、 增量更新
将distAdd文件夹下的所有文件复制到nginx(我用的nginx,其他的同理)下的html文件夹中,覆盖原有的文件,并根据distDel.txt中的文件名称删除原有的的变更文件即可。
注:文档中dist1、distAdd和distDel.txt命名都可在 compare.py中修改
程序代码我放这了:
python版:
# -*-coding:utf-8-*-
#===============================================================================
# 目录对比工具(包含子目录 ),并列出
# 1、A比B多了哪些文件
# 2、B比A多了哪些文件
# 3、二者相同的文件: md5比较
#===============================================================================
import os
import time
import difflib
import hashlib
from shutil import copy
def getFileMd5(filename):
if not os.path.isfile(filename):
print('file not exist: ' + filename)
return
myhash = hashlib.md5()
f = open(filename,'rb')
while True:
b = f.read(8096)
if not b :
break
myhash.update(b)
f.close()
return myhash.hexdigest()
def getAllFiles(path):
flist=[]
for root, dirs , fs in os.walk(path):
for f in fs:
f_fullpath = os.path.join(root, f)
f_relativepath = f_fullpath[len(path):]
flist.append(f_relativepath)
return flist
def dirCompare(apath,bpath):
afiles = getAllFiles(apath)
bfiles = getAllFiles(bpath)
setA = set(afiles)
setB = set(bfiles)
commonfiles = setA & setB # 处理共有文件
difFile = []
for f in sorted(commonfiles):
amd=getFileMd5(apath+'\\'+f)
bmd=getFileMd5(bpath+'\\'+f)
if amd != bmd:
difFile.append(f)
# 处理仅出现在dist目录中的文件
onlyFiles = setA ^ setB
onlyInB = []
for of in onlyFiles:
if of in afiles:
difFile.append(of)
elif of in bfiles:
onlyInB.append(of)
if len(difFile) > 0:
print ('-' * 20,"dif file: %s" %(f), '-' * 20)
newPath = os.getcwd()+'\distAdd'
isExists=os.path.exists(newPath)
if not isExists:
# 创建不同文件存放的目录
os.makedirs(newPath)
for of in sorted(difFile):
print (aPath+of+'---------'+newPath+of)
of2 = of[0:of.rfind('\\')]
if not os.path.exists(newPath+of2):
os.makedirs(newPath+of2)
copy(aPath+of,newPath+of)
if len(onlyInB) > 0:
print ('-' * 20,"only in ", bpath, '-' * 20)
f = open('distDel.txt','w+')
for of in sorted(onlyInB):
f.write(of+'\n')
f.close()
if __name__ == '__main__':
aPath = os.getcwd()+'\\dist'
bPath = os.getcwd()+'\\dist1'
dirCompare(aPath, bPath)
print("\ndone!")
如果没有使用过Python或者电脑没有安装Python的环境的朋友,可以用下面我用Java写的(相应的路径需要根据自己项目的实际路径修改)
java版:
import cn.hutool.core.io.FileUtil;
import org.apache.commons.codec.digest.DigestUtils;
import java.io.*;
import java.util.*;
public class ReportCheckerTest {
/**
* 根据路径获取所有的文件夹和文件,及文件的md5值
*
* @param path 路径
*/
private static Map<String, FileModel> getFiles(String path) throws IOException {
Map<String, FileModel> map = new HashMap<String, FileModel>();
File folder = new File(path);
Object[] files = getFileList(folder).toArray();
Arrays.sort(files);
for (Object obj : files) {
File file = (File) obj;
// 去掉根目录,正则的\\\\,转义为java的\\,再转义为\
String key = file.getAbsolutePath().replaceAll("\\\\", "/").replaceAll(path, "");
String md5 = "";// 文件夹不比较md5值
if (file.isFile()) {
md5 = DigestUtils.md5Hex(new FileInputStream(file));
}
FileModel fileModel = new FileModel(file, md5);
map.put(key, fileModel);
}
return map;
}
/**
* 递归获取路径下所有文件夹和文件
*
* @param folder 文件路径
*/
private static List<File> getFileList(File folder) {
List<File> list = new ArrayList<File>();
File[] files = folder.listFiles();
for (File file : files) {
list.add(file);
if (file.isDirectory()) {
List<File> fileList = getFileList(file);
list.addAll(fileList);
}
}
return list;
}
/**
* 比较两个文件集合的不同
*
* @param fileMap1 文件集合
* @param fileMap2 文件集合
*/
public static List<FileModel> compareFile(Map<String, FileModel> fileMap1, Map<String, FileModel> fileMap2,Boolean checkMd5) {
List<FileModel> list = new ArrayList<FileModel>();
for (String key : fileMap1.keySet()) {
FileModel fileModel1 = fileMap1.get(key);
FileModel fileModel2 = fileMap2.get(key);
// 将fileMap2中没有的文件夹和文件,添加到结果集中
if (fileModel2 == null) {
list.add(fileModel1);
continue;
}
// 文件的md5值不同则add到比较结果集中
if (checkMd5 && fileModel1.getFile().isFile() && !fileModel1.getMd5().equals(fileModel2.getMd5())) {
list.add(fileModel1);
}
}
return list;
}
public static void main(String[] args) throws IOException {
//上一版本dist文件路径
String pathOld = "D:/workspace/appProject/vue/dist1";
//最新版本dist文件路径
String pathNew = "D:/workspace/appProject/vue/dist";
//记录待删除文件的文本路径
String distDel = "D:/workspace/appProject/vue/distDel.txt";
//新增文件的文件夹路径
String distAdd= "D:/workspace/appProject/vue/distAdd";
File fileOld = new File(pathOld);
File fileNew = new File(pathNew);
if (!fileOld.exists() || !fileNew.exists()) {
System.out.println("请检查路径是否存在!");
return;
}
// 获取路径下所有文件夹和文件,及文件的md5值
Map<String, FileModel> fileMap1 = getFiles(pathOld);
Map<String, FileModel> fileMap2 = getFiles(pathNew);
List<FileModel> resultList = new ArrayList<FileModel>();
List<FileModel> resultList2 = new ArrayList<FileModel>();
// 得到fileMap2中没有的文件夹和文件,及md5值不同的文件
resultList.addAll(compareFile(fileMap1, fileMap2,false));
// 得到fileMap1中没有的文件夹和文件,及md5值不同的文件
resultList2.addAll(compareFile(fileMap2, fileMap1,true));
//将旧的文件名称及路径写入到txt文件中
String pathTxt = "";
for (FileModel fileModel : resultList) {
System.out.println("old-----" + fileModel.getFile().getAbsolutePath());
pathTxt += fileModel.getFile().getAbsolutePath() + "\n";
}
try {
File file = new File(distDel);
boolean b = file.createNewFile();
if (b) {
Writer out = new FileWriter(file);
out.write(pathTxt);
out.close();
}
} catch (Exception e) {
e.printStackTrace();
}
//将新生成的文件复制到另一文件夹中
File file2 = new File(distAdd);
if (!file2.exists()) {
file2.mkdirs();
}
for (FileModel fileModel : resultList2) {
System.out.println("new-----" + fileModel.getFile().getAbsolutePath());
String filePath = fileModel.getFile().getAbsolutePath().replace("dist", "distAdd");
FileUtil.copy(fileModel.getFile().getAbsolutePath(), filePath, true);
}
}
}
FileModel:
import java.io.File;
public class FileModel {
public File file;
public String md5;
public FileModel(File file, String md5) {
this.file = file;
this.md5 = md5;
}
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
public String getMd5() {
return md5;
}
public void setMd5(String md5) {
this.md5 = md5;
}
}