Heroku生产环境替换process.env的语法咨询(附代码)
Alright, let's work through this problem. Since you've already got your production environment sorted on Heroku using heroku config:set (no .env file needed there), we just need to adjust your development setup to replace the process.env syntax with a secure, local alternative that keeps your sensitive keys safe.
Here's a tailored step-by-step solution for your code:
1. Create a local development config file
First, make a new file in your project root called dev-config.js (add this file to .gitignore right away—you don't want to commit your private keys):
module.exports = { GEOCODER_API_KEY: "your-google-geocoder-api-key-here", CLOUDINARY_API_KEY: "your-cloudinary-api-key-here", CLOUDINARY_API_SECRET: "your-cloudinary-api-secret-here" };
2. Update your route code to use environment-specific config
At the top of your route file, add logic to load the right config based on whether you're in production or development. Then swap out all instances of process.env.XXX with this new config object:
//----------------------------------------------------------------------------// //--------------------------Dependencies For Route----------------------------// //----------------------------------------------------------------------------// var express = require("express"); var router = express.Router(); var Campground = require("../models/campground"); var middleware = require("../middleware"); var NodeGeocoder = require('node-geocoder'); var multer = require('multer'); var async = require("async"); // Load config: use Heroku env vars in production, local dev config otherwise const config = process.env.NODE_ENV === 'production' ? process.env : require('../dev-config'); // Double-check the path matches where you saved dev-config.js //Node Geocoder API Configuration var options = { provider: 'google', httpAdapter: 'https', apiKey: config.GEOCODER_API_KEY, // Replace process.env with config here formatter: null }; var geocoder = NodeGeocoder(options); //Multer Storage var storage = multer.diskStorage({ filename: function(req, file, callback) { callback(null, Date.now() + file.originalname); } }); //Multer Filter var imageFilter = function (req, file, cb) { // accept image files only if (!file.originalname.match(/\.(jpg|jpeg|png|gif)$/i)) { return cb(new Error('Only image files are allowed!'), false); } cb(null, true); }; //Storing Image + Filter var upload = multer({ storage: storage, fileFilter: imageFilter}); //Cloudinary Configuration var cloudinary = require('cloudinary'); cloudinary.config({ cloud_name: 'dnposhqpc', api_key: config.CLOUDINARY_API_KEY, // Swap process.env here too api_secret: config.CLOUDINARY_API_SECRET // And here }); // INDEX - SHOW ALL CAMPGROUNDS router .get("/", function(req, res){ var perPage = 8; var pageQuery = parseInt(req.query.page); var pageNumber = pageQuery ? pageQuery : 1; var noMatch = null; if (req.query.search) { const regex = new RegExp(escapeRegex(req.query.search), 'gi'); // GET ALL CAMPGROUNDS FROM THE DB Campground.find({"name": regex}, function(err, allCampgrounds){ if(err || !allCampgrounds){ console.log(err); req.flash("error", "Something went wrong!"); } else { if(allCampgrounds.length < 1){ noMatch = "No campground match that query, please try again."; } res.render("campgrounds/index", {campgrounds:allCampgrounds, page: 'campgrounds', noMatch: noMatch}); } }); } else { Campground.find({}).skip((perPage * pageNumber) - perPage).limit(perPage).exec( function(err, allCampgrounds){ Campground.count().exec(function (err, count) { if(err) { console.log(err); } else { res.render("campgrounds/index", {campgrounds:allCampgrounds, page: 'campgrounds', noMatch: noMatch, current: pageNumber, pages: Math.ceil(count / perPage)}); } }); }) } }); //----------------------------------------------------------------// //-----------------CREATE NEW CAMPGROUNDS -----------// //----------------------------------------------------------------// //CREATE - ADD NEW CAMPGROUND TO DB router.post("/", middleware.isLoggedIn, upload.single('image'), function(req, res){ // local variables // Request The Name var name = req.body.name; // Request The Image var image = req.body.image; var imageId = req.body.imageId; // Request The descriptions var desc = req.body.descriptions; // Request The Price var price = req.body.price; // Request The Author's ID + Username var author = { id: req.user._id, username: req.user.username }; //Location Code - Geocode Package geocoder.geocode(req.body.location, function (err, data ) { //Error Handling For Autocomplete API Requests if (err || data.status === 'ZERO_RESULTS') { req.flash('error', 'Invalid address, try typing a new address'); return res.redirect('back'); } if (err || data.status === 'REQUEST_DENIED') { req.flash('error', 'Something Is Wrong Your Request Was Denied'); return res.redirect('back'); } if (err || data.status === 'OVER_QUERY_LIMIT') { req.flash('error', 'All Requests Used Up'); return res.redirect('back'); } var lat = data[0].latitude; var lng = data[0].longitude; var location = data[0].formattedAddress; //Upload Image to Cloudinary cloudinary.uploader.upload(req.file.path, function (result) { image = result.secure_url; imageId= result.public_id; //Captures All Objects And Stores Them var newCampground = {name: name, image: image, description: desc, price: price, author:author, location: location, lat: lat, lng: lng}; // Fixed truncated "locat" here // Rest of your code to save the campground to the DB goes here }); }); });
3. Set your development environment flag
Update your package.json scripts to tell Node you're in development mode when running locally:
"scripts": { "start": "node app.js", "dev": "NODE_ENV=development node app.js" }
- If you're on Windows, use
set NODE_ENV=development && node app.jsinstead, or install thecross-envpackage for cross-platform compatibility.
Quick Notes:
- Heroku automatically sets
NODE_ENVtoproduction, so your production code will still pull variables from the config you set viaheroku config:set. - Never commit
dev-config.jsto version control—keep it locked in.gitignoreto protect your keys. - I fixed the truncated
location: locatline in your code snippet since it was cut off, make sure to finish that section with the full campground object properties.
内容的提问来源于stack exchange,提问作者Saint Everest

