When I'm trying to build my Next.js app for production I got the following error:
Seems 'API_KEY' is undefined. Can't destructure this property from publicRuntimeConfig. This error happens on pages where I use getStaticProps or getStaticPaths built in functions.
Here is my next.config.js:
const withPlugins = require("next-compose-plugins");
const withCSS = require("#zeit/next-css");
const withSass = require("#zeit/next-sass");
const withBundleAnalyzer = require("#next/bundle-analyzer");
const nextRuntimeDotenv = require("next-runtime-dotenv");
const withConfig = nextRuntimeDotenv({ public: ["API_URL", "API_KEY"] });
const nextConfig = {
analyzeServer: ["server", "both"].includes(process.env.BUNDLE_ANALYZE),
analyzeBrowser: ["browser", "both"].includes(process.env.BUNDLE_ANALYZE),
bundleAnalyzerConfig: {
server: {
analyzerMode: "static",
reportFilename: "../bundles/server.html",
},
browser: {
analyzerMode: "static",
reportFilename: "../bundles/client.html",
},
},
publicRuntimeConfig: {
PROXY_MODE: process.env.PROXY_MODE,
API_URL: process.env.API_URL,
API_KEY: process.env.API_KEY,
STATIC_PATH: process.env.STATIC_PATH,
},
};
module.exports = withConfig(
withPlugins([[withCSS], [withSass], [withBundleAnalyzer]], nextConfig)
);
I have researched official docs and google similar problem but seems with no result. Any ideas why Next.js yarn build failed?
From the documentation you can find this. A page that relies on publicRuntimeConfig must use getInitialProps ( https://nextjs.org/docs/api-reference/next.config.js/runtime-configuration ) I think you should put it somewhere else. Check the environment variables section https://nextjs.org/docs/api-reference/next.config.js/environment-variables
Related
I'm following a simple example with NextJS running an Apollo GraphQL server with the package apollo-server-micro. I basically have this:
import { ApolloServer, makeExecutableSchema, } from "apollo-server-micro";
import responseCachePlugin from 'apollo-server-plugin-response-cache';
const typeDefs = require("../../apolloserver/schema");
const { Query } = require("../../apolloserver/resolvers");
const resolvers = {
Query
};
const schema = makeExecutableSchema({ typeDefs, resolvers });
const apolloServer = new ApolloServer({
schema,
context(ctx) {
return {...ctx,prisma};
},
resolvers,
plugins: [responseCachePlugin()]
});
export const config = {
api: {
bodyParser: false,
},
};
export default apolloServer.createHandler({ path: "/api/graphql" });
And when I add the Cache Control to my resolver as follows, I get an error saying
Cannot read property 'cacheControl' of undefined
async function codeCampYears(parent: any, args: any, context: any, info: any) {
console.log(`[${new Date().toLocaleTimeString()}] Query.MyTable`);
info.cacheControl.setCacheHint({ maxAge: 10 });
const data = await context.prisma.MyTable.findMany();
I'm unable to get my stylesheet to apply to my handlebars. Using this exact same code it was able to load yesterday but now I'm getting this MIME error. So I'm not quite sure why this is happening. Any help would be appreciated.
Server Code
const sequelize = require('./config/connection');
const SequelizeStore = require('connect-session-sequelize')(session.Store);
const app = express();
const PORT = process.env.PORT || 3001;
// Set up Handlebars.js engine with custom helpers
const hbs = exphbs.create({ helpers });
const sess = {
secret: 'Super secret secret',
cookie: {},
resave: false,
saveUninitialized: true,
store: new SequelizeStore({
db: sequelize
})
};
app.use(session(sess));
// Inform Express.js on which template engine to use
app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static(path.join(__dirname, 'public')));
app.use(routes);
sequelize.sync({ force: false }).then(() => {
app.listen(PORT, () => console.log('Now listening'));
});
main.handlebars link reference
<link rel="stylesheet" type="text/css" href="/css/style.css">
Folder Org
server
public
--css
--style.css
I figured it out. My Folder org was NOT in face as I said it was, and when I moved my css folder under public everything worked again.
I need my app to work well on a subfolder of the main domain. Exactly here
At first I had a plenty of errors of scripts, css and images not being loaded.
I added the following to next.config.js:
basePath: "/out",
Now scripts and css are working well when exported, they have the /out/ in the path.
However the files do not have yet the /out/ in the path, thus they are giving 404 errors.
I tried to follow this tutorial, but it looks like I am still doing something wrong,
My next.config.js now is:
const path = require("path");
module.exports = {
trailingSlash: true,
sassOptions: {
includePaths: [path.join(__dirname, "styles")],
},
basePath: "/out",
assetPrefix: process.env.BASE_PATH || '',
publicRuntimeConfig: {
basePath: process.env.BASE_PATH || '',
},
};
The relevant piece of the package.json is:
"scripts": {
"dev": "node server.js -p $PORT",
"build": "next build",
"prod": "BASE_PATH=/out next build && next export",
"start": "NODE_ENV=production node server.js -p $PORT",
"start2": "next start"
},
The server.js is:
const express = require('express');
const next = require('next');
const path = require('path');
const bodyParser = require('body-parser');
const keys = require("./server/config/keys");
const stripe = require('stripe')(keys.stripeSecretKey);
const routes = require('./routes');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dir: '.', dev });
const handle = routes.getRequestHandler(app);
app.prepare().then(() => {
const server = express();
// Static files
// https://github.com/zeit/next.js/tree/4.2.3#user-content-static-file-serving-eg-images
server.use('/images', express.static(path.join(__dirname, 'images'), {
maxAge: dev ? '0' : '365d'
}));
server.use(bodyParser.json());
server.get('*', (req, res) => {
return handle(req, res)
});
server.post('/api/stripe/checkout', async (req, res) => {
await stripe.charges.create({
amount: req.body.amount,
currency: 'usd',
description: 'Mojosa - React Next Landing Page Templates',
source: req.body.token.id
});
res.send({})
});
const PORT = process.env.PORT || 3000;
server.listen(PORT, (err) => {
if (err) throw err
console.log(`> Read on http://localhost:${PORT}`)
});
})
And here is an example of an image in a component:
<div className="col-lg-6 col-md-12">
<div className="book-image">
<img src='/images/book-img.png' alt="image" />
</div>
With this configuration:
EXPORT - next build && next export on the /out/ folder are working well when uploaded to the live website, BUT images are giving 404
DEV or BUILD they are giving 404 and working much worse than the EXPORT site published on the real domain. If I remove basePath: "/out", the dev mode works excellent
Questions:
How can I make the /out/ path be added to all the images/assets?
I am ok to re-add basePath: "/out",` when exporting.
Just ran into this one too. You'll need to manually prefix anything in your public folder with your basePath (images, fonts etc)
Docs
"Files in the public folder; if you want to serve those assets over a CDN, you'll have to introduce the prefix yourself"
<div className="col-lg-6 col-md-12">
<div className="book-image">
<img src={`${process.env.BASE_PATH}/images/book-img.png`} alt="image" />
</div>
I'm received error with gatsby develop. It's very similar to this one: https://github.com/firebase/firebase-js-sdk/issues/2222, but I'm received error with gatsby develop, not with gatsby build. I did a lot of research but I can't find working solution.
At first I had a problem with gatsby build, like in this post: https://github.com/firebase/firebase-js-sdk/issues/2222, but I resolved it with custom onCreateWebpackConfig(you can find it below).
Stack:
- Gatsby
- Firebase(error probably with that)
- Redux
I'm also delete .cache and node_modules and install everything again, but it didn't work.
Error:
There was an error compiling the html.js component for the development server.
See our docs page on debugging HTML builds for help https://gatsby.dev/debug-html ReferenceError: IDBIndex is not defined
]);
86 |
> 87 | proxyRequestMethods(Index, '_index', IDBIndex, [
| ^
88 | 'get',
89 | 'getKey',
90 | 'getAll',
WebpackError: ReferenceError: IDBIndex is not defined
- idb.mjs:87 Module../node_modules/idb/lib/idb.mjs
node_modules/idb/lib/idb.mjs:87:1
- index.esm.js:1 Module../node_modules/#firebase/installations/dist/index.esm.js
node_modules/#firebase/installations/dist/index.esm.js:1:1
- index.esm.js:1 Module../node_modules/#firebase/analytics/dist/index.esm.js
node_modules/#firebase/analytics/dist/index.esm.js:1:1
- index.esm.js:1 Module../node_modules/firebase/analytics/dist/index.esm.js
node_modules/firebase/analytics/dist/index.esm.js:1:1
- index.ts:1 Module../src/firebase/index.ts
src/firebase/index.ts:1:1
- index.esm.js:32 emit
node_modules/#firebase/analytics/dist/index.esm.js:32:1
My gatsby-node file:
exports.onCreateWebpackConfig = ({ stage, actions, getConfig }) => {
if (stage === 'build-html') {
actions.setWebpackConfig({
externals: getConfig().externals.concat(function(context, request, callback) {
const regex = /^#?firebase(\/(.+))?/;
if (regex.test(request)) {
return callback(null, `umd ${request}`);
}
callback();
}),
});
}
};
My firebase dependencies:
"#firebase/firestore-types": "^1.10.1",
"firebase": "^7.13.1",
"firebase-admin": "^8.10.0",
"firebase-functions": "^3.5.0",
"firebase-tools": "^7.16.1",
Firebase index file:
import firebase from 'firebase/app';
import 'firebase/firestore';
import 'firebase/auth';
import 'firebase/storage';
import 'firebase/analytics';
const firebaseConfig = {...};
firebase.initializeApp(firebaseConfig);
export const firestore = firebase.firestore();
export const auth = firebase.auth();
export const storage = firebase.storage();
Project repo: https://github.com/olafsulich/Projecty
Post on Github issues: https://github.com/firebase/firebase-js-sdk/issues/2946
Thanks in advance.
The following snippet will only work on build environment because of your condition (stage === 'build-html'):
exports.onCreateWebpackConfig = ({ stage, actions, getConfig }) => {
if (stage === 'build-html') {
actions.setWebpackConfig({
externals: getConfig().externals.concat(function(context, request, callback) {
const regex = /^#?firebase(\/(.+))?/;
if (regex.test(request)) {
return callback(null, `umd ${request}`);
}
callback();
}),
});
}
};
Remove it and use it like this:
exports.onCreateWebpackConfig = ({ stage, actions, getConfig }) => {
actions.setWebpackConfig({
externals: getConfig().externals.concat(function(context, request, callback) {
const regex = /^#?firebase(\/(.+))?/;
if (regex.test(request)) {
return callback(null, `umd ${request}`);
}
callback();
}),
});
};
Thank's a lot! It's working only on gatbsy develop, but now when I
want to build project, I get an error - TypeError: Cannot read
property 'concat' of undefined. You know how to solve it?
Regarding the new issue, you can follow a workaround in this topic, This is a common error in third-party modules in Gatsby when they try to reach a DOM element (usually window) that is not already defined when the app builds. So, you need to wait until window is defined. You can achieve this in two ways:
Instancing your firebase with a condition like this:
import firebase from '#firebase/app';
import '#firebase/auth';
import '#firebase/firestore';
import '#firebase/functions';
const config = {
... firebase config here
};
let instance;
export default function getFirebase() {
if (typeof window !== 'undefined') {
if (instance) return instance;
instance = firebase.initializeApp(config);
return instance;
}
return null;
}
Note the if (typeof window !== 'undefined') statement
By ignoring firebase module in you webpack configuration like shows their docs. In your gatsby-node.js:
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
if (stage === "build-html") {
actions.setWebpackConfig({
module: {
rules: [
{
test: /bad-module/,
use: loaders.null(),
},
],
},
})
}
}
Replace bad module for firebase (or the package/folder name in node_modules). Leave the slashes since test is a regular expression rule
This snippet replaces your previous one that seems to throw an error in concat() function.
For those who wants to try the concat() resolution, this will be helpful too:
exports.onCreateWebpackConfig = ({ stage, actions, getConfig }) => {
if (stage === 'build-html') {
actions.setWebpackConfig({
externals: getConfig().externals.concat((context, request, callback) => {
const regex = /^#?firebase(\/(.+))?/
// exclude firebase products from being bundled, so they will be loaded using require() at runtime.
if (regex.test(request)) {
return callback(null, `commonjs ${request}`) // <- use commonjs!
}
callback()
}),
})
}
}
Solved this problem!!
I'm using "gatsby": "^3.10.2", "firebase": "9.0.0-beta.6".
firebase needs to be set externals as commonjs.
gatsby-node.js:
exports.onCreateWebpackConfig = ({ stage, actions, getConfig }) => {
if (stage === 'build-html') {
actions.setWebpackConfig({
externals: getConfig().externals.concat((context, request, callback) => {
const regex = /^#?firebase(\/(.+))?/
// exclude firebase products from being bundled, so they will be loaded using require() at runtime.
if (regex.test(request)) {
return callback(null, `commonjs ${request}`) // <- use commonjs!
}
callback()
}),
})
}
}
Please try this setting.
I'm writing a Next.js app with a custom server.js file and I can't load my css - I keep getting the following in the browser console:
The resource from “http://localhost:3000/_next/
static/development/pages/index.js?ts=1552499710032”
was blocked due to MIME type (“text/html”)
mismatch (X-Content-Type-Options: nosniff)
and I don't know why. As far as I can tell I have configured my app as I had done for a previous working version. Here is my next.config.js file:
const withCSS = require('#zeit/next-css');
const withImages = require('next-images');
const path = require('path')
const Dotenv = require('dotenv-webpack')
require('dotenv').config()
module.exports = withImages(withCSS({
webpack: config => {
// Fixes npm packages that depend on `fs` module
config.node = {
fs: 'empty'
}
config.plugins = config.plugins || []
config.plugins = [
...config.plugins,
// Read the .env file
new Dotenv({
path: path.join(__dirname, '.env'),
systemvars: true
})
]
return config
}
}))
And here is my server.js file:
const express = require('express')
const next = require('next')
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
const path = require('path');
const options = {
root: path.join(__dirname, '/static'),
headers: {
'Content-Type': 'text/plain;charset=UTF-8',
}
};
app.prepare().then(() => {
const server = express()
server.get('/robots.txt', (req, res) => {
return res.status(200).sendFile('robots.txt', options)
});
server.get('/sitemap.xml', (req,res) => {
return res.status(200).sendFile('sitemap.xml', options)
});
server.get('/', (req, res) => {
return app.render(req, res, '/', req.query)
})
server.listen(port, err => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
I run my app by using node server.js and I import the css using import "./styles/root.css" (my one and only css file) so no surprises there. What is going wrong?
EDIT: This is trivial enough that it may be a bug. I've opened a report here: https://github.com/zeit/next.js/issues/6647.
You are missing
server.get('*', (req, res) => {
return handle(req, res)
})
in your server.js. your github repo will work fine if you uncomment the above code and restart the server