如何使用next在AWS S3上托管静态文件? [英] How do I host static files on AWS S3 using next?

查看:134
本文介绍了如何使用next在AWS S3上托管静态文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我来自Django背景,静态文件主要存储在S3上,我想了解它在NodeJS上的工作原理,因为我想将应用程序从Django/React迁移到NodeJS/NextJS/ExpressJS/反应.

I'm coming from Django background where static files are mostly stored on S3, I'm trying to understand how it works on NodeJS since I'd like to migrate an app from Django/React to NodeJS/NextJS/ExpressJS/React.

我不了解&在生产环境中将我的静态文件(客户端js,css,图像)存储在哪里?我想知道如何上传到s3 并管理动态文件,因为该工作是由用户通过express api完成的,但是我正在寻找可以在部署时将所有公共文件批量上传到s3的东西(这是甚至与快递相关的正确方法?).

I don't get how & where to store my static files (client side js, css, images) on a production environment? I think to know how to upload to s3 and manage dynamic files since the work is done by the users through the express api, but I'm searching for something where I can batch upload all the public files to s3 on deploy (is this even the right way to do with express?).

由于我想部署到Heroku,所以我知道它们有一个不保留那些静态文件的策略,(在Django中,每次部署时我都使用"collectstatic"命令将所有静态文件批量上传到S3),如何&您从哪里在这里提供这些文件?

Since I'd like to deploy to Heroku I know that they have a policy of not keeping those static files, (In Django I use "collectstatic" command to batch upload all my static files to S3 on each deploy), how & from where do you serve those files in here?

任何建议都会有所帮助.

Any advice would help.

推荐答案

next.config.js ,设置

next.config.js, set assetPrefix to aws s3 link in production.

const isDev = process.env.NODE_ENV !== 'production';
const version = require('./package.json').version;

assetPrefix: isDev ? '' : `https://${process.env.AWS_REGION}.amazonaws.com/${process.env.AWS_S3_BUCKET_NAME}/${version}`,

collectstatic.js ,在构建后的版本上运行.

collectstatic.js, run on postbuild release.

require('dotenv').config();
const fs = require('fs');
const readDir = require('recursive-readdir');
const path = require('path');
const AWS = require('aws-sdk');
const mime = require('mime-types');
const version = require('./package.json').version;

// You will run this script from your CI/Pipeline after build has completed.
// It will read the content of the build directory and upload to S3 (live assets bucket)
// Every deployment is immutable. Cache will be invalidated every time you deploy.
AWS.config.update({
  region: process.env.AWS_S3_REGION,
  accessKeyId: process.env.AWS_S3_ACCESS_KEY,
  secretAccessKey: process.env.AWS_S3_SECRET_KEY,
  maxRetries: 3
});

// Retrive al the files path in the build directory
const getDirectoryFilesRecursive = (dir, ignores = []) => {
  return new Promise((resolve, reject) => {
    readDir(dir, ignores, (err, files) => (err ? reject(err) : resolve(files)));
  });
};

// The Key will look like this: _next/public/<buildid>/pages/index.js
// the <buildid> is exposed by nextJS and it's unique per deployment.
// See: https://nextjs.org/blog/next-7/#static-cdn-support
const generateFileKey = (fileName, toReplace, replaced) => {
  // I'm interested in only the last part of the file: '/some/path/.next/build-manifest.json',
  const S3objectPath = fileName.split(toReplace)[1];
  return version + replaced + S3objectPath;
};

const s3 = new AWS.S3();

const uploadToS3 = async (fileArray, toReplace, replaced) => {
  try {
    fileArray.map(file => {
      // Configuring parameters for S3 Object
      const S3params = {
        Bucket: process.env.AWS_S3_BUCKET_NAME,
        Body: fs.createReadStream(file),
        Key: generateFileKey(file, toReplace, replaced),
        ACL: 'public-read',
        ContentType: String(mime.lookup(file)),
        ContentEncoding: 'utf-8',
        CacheControl: 'immutable,max-age=31536000,public'
      };

      s3.upload(S3params, function(err, data) {
        if (err) {
          // Set the exit code while letting
          // the process exit gracefully.
          console.error(err);
          process.exitCode = 1;
        } else {
          console.log(`Assets uploaded to S3:`, data.key);
        }
      });
    });
  } catch (error) {
    console.error(error);
  }
};

// Start function
// getDirectoryFilesRecursive(path, ignore);
const start = async function(dict) {
  for (var i = 0; i < dict.length; i++) {
    const files = await getDirectoryFilesRecursive(path.resolve(__dirname, dict[i].filePath), ['.DS_Store', 'BUILD_ID']);
    uploadToS3(files, dict[i].toReplace, dict[i].replaced);
  }
}

// Call start
start([
  {
    filePath: '.next',
    toReplace: '.next/',
    replaced: '/_next/'
  }
]);

然后运行node collectstatic.js将您的所有资产上传到S3.

Then run node collectstatic.js to uploade all your assets to S3.

这篇关于如何使用next在AWS S3上托管静态文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆