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

查看:18
本文介绍了如何使用 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 并管理 dynamic 文件,因为工作是由用户通过 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,设置assetPrefix 到生产中的 aws s3 链接.

next.config.js, set assetPrefix to your 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.

Run node collectstatic.js to upload all your assets to S3.

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

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