⚡Node.js在前端代码部署中的实践应用

1,593 阅读6分钟

Node.js是一个开源且跨平台的JavaScript运行时环境,它允许开发者在服务器端运行JavaScript代码。这一特性打破了JavaScript仅能在浏览器中运行的局限,拓展了JavaScript的应用范围。

这篇文章就来介绍一下Node.js在前端部署中的实践应用。

1.前端部署的几种方式

前端代码的部署方式多样,可以根据项目的规模、目标平台、性能需求和安全要求来选择最适合的部署策略。以下是一些常见的前端代码部署方式:

1. 手动部署

  • FTP上传:通过文件传输协议(FTP)手动上传打包后的静态文件到服务器。这种方式简单直接,但随着项目复杂度增加,手动操作的错误率也会提高。
  • 直接复制:对于小型项目或临时部署,开发者有时会直接将构建好的文件复制到服务器上。

2. 使用版本控制系统

  • Git部署:利用Git钩子或第三方服务(如GitHub Pages或GitLab Pages)自动将代码部署到服务器。这种方式可以与项目的版本控制系统紧密集成,自动化程度高。

3. 持续集成/持续部署(CI/CD)

  • CI/CD平台:使用如Jenkins、Travis CI、CircleCI、GitHub Actions等工具自动化测试、构建和部署流程。这种方式可以大大提高开发效率和代码质量,适合团队开发。

4. 云服务平台

  • 静态网站托管服务:如Netlify、Vercel、Amazon S3加CloudFront、Firebase Hosting等,这些平台提供简单快速的静态网站部署服务,通常包括CDN加速、HTTPS支持等特性。
  • 容器部署:通过Docker等容器技术将应用容器化,然后部署到Kubernetes或其他容器管理平台。适合大型、复杂应用的部署。

2. 使用Node.js代替手动部署

现公司是使用最原始的部署方式:手动部署,很显然,手动部署会存在一些问题:

  1. build完代码需要手动压缩,生成zip文件。
  2. 需要使用”远程桌面连接“连接服务器。
  3. 需要找到相应的目录。
  4. 将本机的压缩包拷到服务器对应目录并解压。

这样操作会很繁琐,而且及容易出错,例如将部署代码放在了错误的目录下。

”懒惰“可是程序员的一大美德,我们可以借助nodejs实现上述90%的操作,何乐而不为呢?

借助的npm包

archiver

image.png

archiver是一个Node.js的npm包,主要用于生成归档文件,如ZIP或TAR格式。它提供了一个通过JavaScript代码简单生成归档文件的方法,支持流式接口,可以很容易地与Node.js应用集成。archiver非常适合在需要程序化创建压缩文件的场景中使用,如自动化备份、打包部署文件等。

主要特性包括:

  • 支持多种格式:默认支持ZIP和TAR格式的归档,其中ZIP格式还支持压缩。
  • 流式API:可以将文件或数据流直接添加到归档中,支持大文件的高效处理。
  • 灵活的文件添加:可以从文件系统、缓存或任何可读流中添加文件到归档中。
  • 自定义选项:支持设置归档级别的选项,如压缩级别、归档注释等。
  • 事件监听:可以监听各种事件,如进度、警告和错误,方便进行日志记录或处理特殊情况。

借助archive压缩文件的能力,我们先压缩dist目录的内容。

执行部署的文件我们放置于项目根目录

const path = require('path');
const archiver =require('archiver');
const fs = require('fs');
const srcPath = path.resolve(__dirname,'./dist');

//压缩dist目录为dist.zip
function startZip() {
    console.log('开始压缩dist目录...');
    var archive = archiver('zip', {
        zlib: { level: 5 }              //递归扫描最多5层
    }).on('error', function(err) {      
        throw err;                      //压缩过程中如果出现错误则抛出
    });

    var output = fs.createWriteStream(__dirname + '/dist.zip')
    .on('close', function(err) {
        /*压缩结束时要先触发close事件,然后开始上传,
          否则会上传一个内容不全且无法使用的zip包*/
        if (err) {
            console.log('压缩zip文件异常:',err);
            return;
        }
        console.log('已生成zip包');
        // uploadFile(); 后续上传代码逻辑
    });
    archive.pipe(output);               //典型的node stream用法

    //将srcPath路径对应的内容添加到zip包的"/"路径中
    archive.directory(srcPath,'/');
    archive.finalize();
}

node-ssh

image.png

node-ssh 是一个基于Node.js的npm包,它提供了一个简单的接口来执行SSH(Secure Shell)操作,使得在Node.js应用中可以轻松地连接到SSH服务器、执行命令、传输文件等。这个库底层使用了ssh2客户端库,ssh2是一个纯JavaScript实现的SSH2客户端协议,提供了与SSH服务器交互的能力。

node-ssh的主要功能包括:

  • 执行远程命令:可以连接到SSH服务器,并执行一条或一系列命令。
  • 上传和下载文件:支持通过SSH将本地文件上传到远程服务器,或从远程服务器下载文件。
  • 目录上传和下载:提供将整个目录上传到远程服务器或从远程服务器下载整个目录的能力。

借助node-ssh连接服务器并上传文件的能力,我们来试一试。

//将dist目录上传至正式环境
function uploadFile() {
    // 先连接
    ssh.connect({                       //configs中存放的是连接远程机器的信息
        host: configs.host,
        username: configs.user,
        password: configs.password,
        // port:22 //SSH默认的连接端口号为22
    }).then(function () {
      console.log('连接成功');
        //将网站的发布包上传至configs中配置的远程服务器的指定地址中
        const path ='xxx'
        ssh.putFile(__dirname + '/dist.zip', `${path}/dist.zip`).then(function(status) {
            console.log('上传文件成功');
            console.log('请前往服务器解压');
            process.exit(0);
            }).catch(err=>{
                console.log('文件传输异常:',err);
                process.exit(0);
            });
    }).catch(err=>{
        console.log('ssh连接失败:',err);
        process.exit(0);
    });
}

3. 如何启动部署

  1. 配置脚本
    "scripts": {
        "deploy": "node deploy.js",
    },
  1. deploy.js执行startZip()函数

然后就可以仅需要解压一下上传的zip包就部署完成了

完整代码:

const path = require('path');
const archiver =require('archiver');
const fs = require('fs');
const {NodeSSH} = require('node-ssh');
const ssh = new NodeSSH();
const srcPath = path.resolve(__dirname,'./dist');
const configs = require('./config');
console.log(configs);
startZip();

//压缩dist目录为dist.zip
function startZip() {
    console.log('开始压缩dist目录...');
    var archive = archiver('zip', {
        zlib: { level: 5 }              //递归扫描最多5层
    }).on('error', function(err) {      
        throw err;                      //压缩过程中如果出现错误则抛出
    });

    var output = fs.createWriteStream(__dirname + '/dist.zip')
    .on('close', function(err) {
        /*压缩结束时要先触发close事件,然后开始上传,
          否则会上传一个内容不全且无法使用的zip包*/
        if (err) {
            console.log('压缩zip文件异常:',err);
            return;
        }
        console.log('已生成zip包');
        uploadFile();
    });
    archive.pipe(output);               //典型的node stream用法

    //将srcPath路径对应的内容添加到zip包的"/"路径中
    archive.directory(srcPath,'/');
    archive.finalize();
}

//将dist目录上传至正式环境
function uploadFile() {
    ssh.connect({                       //configs中存放的是连接远程机器的信息
        host: configs.host,
        username: configs.user,
        password: configs.password,
        // port:22 //SSH默认的连接端口号为22
    }).then(function () {
      console.log('连接成功');
        //将网站的发布包上传至configs中配置的远程服务器的指定地址中
        let path = 'xxx'
        ssh.putFile(__dirname + '/dist.zip', `${path}/dist.zip`).then(function(status) {
            console.log('上传文件成功');
            console.log('请前往服务器解压');
            process.exit(0);
            }).catch(err=>{
                console.log('文件传输异常:',err);
                process.exit(0);
            });
    }).catch(err=>{
        console.log('ssh连接失败:',err);
        process.exit(0);
    });
}

4.需要改进的地方

  1. 区分测试和生产环境 我们可以执行脚本是携带参数,然后在deploy.js中获取参数
    "scripts": {
        "deploy:test": "node deploy.js test",
        "deploy:prod": "node deploy.js prod",
    }

deploy.js:

const arg = process.argv.slice(2)[0];
console.log(arg); // test | prod

2.上传完服务器仍需要解压

解决方案:在deploy.js中,我们可以在连接服务器并上传文件后,执行服务器端的脚本,通过服务器端的脚本执行解压的功能。

这个方案笔者试过,可行,但是可能没找到正确的解压工具,借助脚本使用unzip解压文件,但是居然不能解压出html文件,这个问题还得看看怎么解决,或者选择一个更好的解压工具🛠。

最后

本文介绍了Node.js在前端代码部署中的实践应用,实现了半自动化部署~
如果这篇文章对你有帮助的话,麻烦点赞收藏哟~
笔者还有其他专栏,欢迎阅读~
Vue从放弃到入门
深入浅出JavaScript