手写webpack插件上传前端spa文件到腾讯云cdn


前端spa静态文件上传腾讯云COS,从单点服务器分散到多点cdn,减轻服务器压力,加快加载速度。
1、commonjs格式导出插件webpack-cos-done-plugin,添加到webpack配置plugins
2、插件中提供apply方法,注册DonePlugin事件,当打包完成执行回调函数

class WebpackCosDonePlugin {
  //打包完done插件
  apply(compiler: any) {
    compiler.hooks.done.tap('DonePlugin', () => {
      uploadToCosFn(APP_NAME, appVersion, REACT_APP_ENV, 'dist');
    });
  }
}

3、使用fs.createReadStream读取每个文件流,使用腾讯云cos-nodejs-sdk-v5中的cos.putObject方法上传到cdn

  function uploadToCos() {
    console.log(`==========> 开始上传静态资源到 CDN`);

    dir.files(path.join(process.cwd(), distDir), (err, files) => {
      if (err) {
        if (err.code === 'ENOENT') {
          console.log(`${distDir} 目录不存在`);
        } else {
          console.log(`dir.files error: ${err}`);
        }
        process.exit(1);
      }

      Promise.all(
        files.map((filePath) => {
          return new Promise((resolve, reject) => {
            const readableStream = fs.createReadStream(filePath);

            const uploadFilePath = filePath.match(
              new RegExp(fileRegExpPattern),
            )[1];

            const key = `apps/${appName}/${appVersion}/${uploadFilePath}`;

            console.log('开始上传:' + key);

            cos.putObject(
              {
                Bucket: cosCfg[appEnv].bucketName,
                Region: cosCfg[appEnv].region,
                Key: key,
                StorageClass: 'STANDARD',
                Body: readableStream,
              },
              (err, data) => {
                if (err) {
                  console.log(
                    `${key} 上传失败!? statusCode: ${err.statusCode}`,
                  );
                  process.exit(1);
                }

                if (data.statusCode === 200) {
                  console.log(`==========> ${key} 上传成功~ ??`);
                  resolve(data);
                } else {
                  console.log(
                    `${key} 上传失败!? statusCode: ${data.statusCode}`,
                  );
                  process.exit(1);
                }
              },
            );
          });
        }),
      ).then((result) => {
        replaceIndexFile();
      });
    });
  }

4、当全部文件上传完毕,替换index.html文件到原来位置,nginx指向原来index.html文件

  function replaceIndexFile() {
    console.log(`==========> 开始替换入口文件`);

    const indexFileReadableStream = fs.createReadStream(
      path.join(process.cwd(), `${distDir}/${indexFile}`),
    );

    const indexFileKey = `apps/${appName}/latest/${indexFile}`;

    console.log('开始上传:' + indexFileKey);

    cos.putObject(
      {
        Bucket: cosCfg[appEnv].bucketName,
        Region: cosCfg[appEnv].region,
        Key: indexFileKey,
        StorageClass: 'STANDARD',
        Body: indexFileReadableStream,
      },
      (err, data) => {
        if (err) {
          console.log(
            `${indexFileKey} 上传失败!? statusCode: ${err.statusCode}`,
          );
          process.exit(1);
        }

        if (data.statusCode === 200) {
          console.log(`==========> ${indexFileKey} 上传成功~ ??`);
        } else {
          console.log(
            `${indexFileKey} 上传失败!? statusCode: ${data.statusCode}`,
          );
          process.exit(1);
        }
      },
    );
  }