I have been working on a NextJS application that utilizes Firebase. I have everything set up and on build I get the following error: package.json does not exist at /package.json (see the image)
build error
To give more context on this:
NextJS v^9.3.0
Firebase v^7.10.0
Target: server (by default)
My next.config.js:
const path = require('path')
const resolve = require('resolve')
const withCSS = require('#zeit/next-css')
const withImages = require('next-images')
const withFonts = require('next-fonts')
const withTM = require('next-transpile-modules')([
'*************',
'*************',
'*************'
]);
if (typeof require !== "undefined") {
require.extensions[".less"] = () => {};
require.extensions[".css"] = (file) => {};
}
module.exports =
withCSS(
withImages(
withFonts(
withTM({
webpack: (config, options) => {
config.module.rules.push({
test: /\.svg$/,
use: ['#svgr/webpack'],
});
const { dir, isServer } = options
config.externals = []
if (isServer) {
config.externals.push((context, request, callback) => {
resolve(request, { basedir: dir, preserveSymlinks: true }, (err, res) => {
if (err) {
return callback()
}
if (
res.match(/node_modules[/\\].*\.css/)
&& !res.match(/node_modules[/\\]webpack/)
&& !res.match(/node_modules[/\\]#aws-amplify/)
) {
return callback(null, `commonjs ${request}`)
}
callback()
})
})
}
return config;
},
cssLoaderOptions: {
url: false
}
})
)
)
)
I have been trying many solutions, including the following:
- I should use target server, but I have also tried with "experimental-serverless-trace" but no effect, same error persists
- Tried also "webpack-asset-relocator-loader" but it doesn't work as well. When utilized, I get the following error: "gRPC binary module was not installed".
To be honest, at this point I do not have any idea where to go from this point.
Thanks!
Related
I'm using Prismic and NextJS for the first time.
What I'm trying to is make it so when the user goes to the base url for the page localhost:3000/ in dev something will load. /About and /Pricing are working fine the base url doesn't work.
import { GetStaticPaths, GetStaticProps } from 'next'
import { SliceZone } from '#prismicio/react'
import * as prismicH from "#prismicio/helpers";
import { createClient, linkResolver } from '../../prismicio'
import { components } from '../../slices'
interface HomePageProps {
page: any
}
const HomePage = (props:HomePageProps) => {
return <SliceZone slices={props.page.data.slices} components={components} />
}
export default HomePage
interface HomePageStaticProps {
params: any
previewData:any
}
export async function getStaticProps(props:HomePageStaticProps) {
console.log("DOES NOT FIRE FOR localhost:3000")
const client = createClient({ previewData:props.previewData })
const params = props.params;
const uid = params?.pagePath?.[params.pagePath.length - 1] || "home";
const page = await client.getByUID("page", uid);
return {
props: {
page,
},
}
}
export const getStaticPaths: GetStaticPaths = async () => {
const client = createClient();
const pages = await client.getAllByType("page");
const paths = pages.map((page) => prismicH.asLink(page, linkResolver)) as string[];
console.log(paths) // [ '/pricing', '/about', '/' ]
return {
paths,
fallback: false,
};
}
or to simplify it further
[[...pagePath]].tsx fails when going to localhost:3000/ but does not fail on localhost:3000/about or localhost:3000/pricing.
import { GetStaticPaths, GetStaticProps } from 'next'
interface HomePageProps {
page: string
}
const HomePage = (props:HomePageProps) => {
return <>{props.page}</>
}
export default HomePage
interface HomePageStaticProps {
params: any
previewData:any
}
export async function getStaticProps(props:HomePageStaticProps) {
const params = props.params;
const uid = params?.pagePath?.[params.pagePath.length - 1] || "home";
//const page = await client.getByUID("page", uid);
return {
props: {
page:uid,
},
}
}
export const getStaticPaths: GetStaticPaths = async () => {
const paths = [ '/pricing', '/about', '/' ];
return {
paths,
fallback: false,
};
}
As far as I can see your'e not fetching the right way. In order to to have a clean project I would recommend to use a const var where you can determine between dev and production enviorenment. To do so you can simply create a file for example: constants.js containing the following:
export const baseurl = process.env.NODE_ENV === "production"
? process.env.NEXT_PUBLIC_DOMAIN // <-- your domain on live
: "http://localhost:3000"; // localhost on dev
Now with this you automatically have localhost on your dev. Notice that you need http:// which your'e missing at the moment. Now the next example shows you how to fetch something on your root / by entering the following code:
import { baseurl } from "../utils/constants"; // <-- importing the constant
// This function gets called at build time on server-side.
// It won't be called on client-side, so you can even do
// direct database queries.
export async function getStaticProps() {
// Call an external API endpoint to get posts.
// You can use any data fetching library
const res = await fetch(`${baseurl}/api/posts`)
const posts = await res.json()
// By returning { props: { posts } }, the Blog component
// will receive `posts` as a prop at build time
return {
props: {
posts,
},
}
}
If you are using Create-T3-App
https://github.com/t3-oss/create-t3-app
then
your next.config.mjs will default to this as of Nov 7, 2022
const config = {
reactStrictMode: true,
swcMinify: true,
i18n: {
locales: ["en"],
defaultLocale: "en",
},
};
export default config;
remove
const config = {
reactStrictMode: true,
swcMinify: true,
//i18n: {
// locales: ["en"],
// defaultLocale: "en",
//},
};
export default config;
This will make default "/" pathing work, if you require i18n, I'm sorry I can't help.
I am trying to add react-responsive-carousel to my NextJS project. When i run npm run dev everything seems to be fine, however my carousel is rendered with no styles.
import { Carousel } from 'react-responsive-carousel';
import 'react-responsive-carousel/lib/styles/carousel.min.css'; // requires loader
const MyCarousel = () => {
return (
<Carousel
autoPlay
interval={2500}
showArrows={true}
>
<div>content</div>
<div>content</div>
<div>content</div>
</Carousel>
)
}
Documentation says that styles need a loader so I configures next.config.js as follows
const withLess = require('#zeit/next-less');
const withCss = require('#zeit/next-css');
const withImage = require('next-images');
const theme = require('./app/styles/antdoverrides');
module.exports = withImage(
withCss({
cssModules: true,
optimizeFonts: false,
...withLess({
lessLoaderOptions: {
javascriptEnabled: true,
importLoaders: 0,
modifyVars: {
...theme,
},
},
cssLoaderOptions: {
importLoaders: 3,
localIdentName: '[local]___[hash:base64:5]',
},
webpack5: false,
webpack: (config, { isServer }) => {
if (isServer) {
const antStyles = /antd\/.*?\/style.*?/;
const origExternals = [...config.externals];
config.externals = [
(context, request, callback) => {
if (request.match(antStyles)) return callback();
if (typeof origExternals[0] === 'function') {
origExternals[0](context, request, callback);
} else {
callback();
}
},
...(typeof origExternals[0] === 'function' ? [] : origExternals),
];
config.module.rules.unshift({
test: antStyles,
use: 'null-loader',
});
}
return config;
},
}),
}),
);
still not getting desired result. Any hints appreciated
You need to import your styles in your _app.js file if you don't use the objects. Just in your _app make import of your styles, something like:
import "../styles/globals.css";
Also you need to npm run local or something like this, check your package.json file to run locally your project instead of build
How would I go about precaching all the pages of my nextjs app using next-pwa?. Let's say I have the following pages:
/
/about
/posts
I want all of them to be precached so that they are all available offline once the app has been loaded the first time. At the moment I'm using a custom webpack config to copy the .next/build-manifest.json file over to public/build-manifest. Then once the app loads the first time, I register an activated handler that fetches the build-manifest.json file and then adds them to the cache. It works but it seems like a roundabout way of achieving it, and it depends somewhat on implementation details. How would I accomplish the same in a more canonical fashion?
At the moment, my next.config.js file looks like this
const pwa = require('next-pwa')
const withPlugins = require('next-compose-plugins')
const WebpackShellPlugin = require('webpack-shell-plugin-next')
module.exports = withPlugins([
[
{
webpack: (config, { isServer }) => {
if (isServer) {
config.plugins.push(
new WebpackShellPlugin({
onBuildExit: {
scripts: [
'echo "Transfering files ... "',
'cp -r .next/build-manifest.json public/build-manifest.json',
'echo "DONE ... "',
],
blocking: false,
parallel: true,
},
})
)
}
return config
},
},
],
[
pwa,
{
pwa: {
dest: 'public',
register: false,
skipWaiting: true,
},
},
],
])
And my service worker hook looks like this
import { useEffect } from 'react'
import { Workbox } from 'workbox-window'
export function useServiceWorker() {
useEffect(() => {
if (
typeof window !== 'undefined' &&
'serviceWorker' in navigator &&
(window as any).workbox !== undefined
) {
const wb: Workbox = (window as any).workbox
wb.addEventListener('activated', async (event) => {
console.log(`Event ${event.type} is triggered.`)
console.log(event)
const manifestResponse = await fetch('/build-manifest.json')
const manifest = await manifestResponse.json()
const urlsToCache = [
location.origin,
...manifest.pages['/[[...params]]'].map(
(path: string) => `${location.origin}/_next/${path}`
),
`${location.origin}/about`,
...manifest.pages['/about'].map((path: string) => `${location.origin}/_next/${path}`),
`${location.origin}/posts`,
...manifest.pages['/posts'].map((path: string) => `${location.origin}/_next/${path}`),
]
// Send that list of URLs to your router in the service worker.
wb.messageSW({
type: 'CACHE_URLS',
payload: { urlsToCache },
})
})
wb.register()
}
}, [])
}
Any help is greatly appreciated. Thanks.
I tried to find a way to change the language by changing the site's sub-path in the next-i18next package, I searched the Internet (https://github.com/isaachinman/next-i18next/issues/32 , https://github.com/i18next/i18next-browser-languageDetector#detector-options) for an answer to this question, but it did not work. After changing the subpath in the url it is duplicated and redirects me to a page that does not exist.
my code:
// path-to-my-project/i18n.js
const NextI18Next = require('next-i18next').default;
const i18nextBrowserLanguageDetector = require('i18next-browser-languagedetector').default;
const { localeSubpaths } = require('next/config').default().publicRuntimeConfig;
const path = require('path');
module.exports = new NextI18Next({
otherLanguages: ['ru'],
defaultNS: 'common',
localeSubpaths,
localePath: path.resolve('./public/static/locales'),
use: [i18nextBrowserLanguageDetector],
});
// path-to-my-project/pages/_app.js
import '../styles/main.scss';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import Router from 'next/router';
import App from 'next/app';
import { appWithTranslation } from '../i18n';
Router.events.on('routeChangeStart', () => NProgress.start());
Router.events.on('routeChangeComplete', () => NProgress.done());
Router.events.on('routeChangeError', () => NProgress.done());
const MyApp = ({ Component, pageProps }) => (
<Component {...pageProps} />
);
MyApp.getInitialProps = async (appContext) => ({ ...await App.getInitialProps(appContext) });
export default appWithTranslation(MyApp);
maybe I just missed something, because it's my first project on next.js, so I'm asking for help in the community and would be grateful for any help or hint.
By default next-i18next will try to detect the language to show from users browser.
Try to disable it.
const NextI18Next = require('next-i18next').default
const { localeSubpaths } = require('next/config').default().publicRuntimeConfig
const path = require('path')
module.exports = new NextI18Next({
browserLanguageDetection: false, // <---
serverLanguageDetection: false, // <---
otherLanguages: ['de'],
localeSubpaths,
localePath: path.resolve('./public/static/locales')
})
in file next.config.js i have this settings:
// path/to/project/next.config.js
const { nextI18NextRewrites } = require('next-i18next/rewrites');
const localeSubpaths = {
ru: 'ru',
};
module.exports = {
rewrites: async () => nextI18NextRewrites(localeSubpaths),
publicRuntimeConfig: {
localeSubpaths,
},
devIndicators: {
autoPrerender: false,
},
};
but there was not enough configuration for English localization, so you just need to add it:
// path/to/project/next.config.js
const { nextI18NextRewrites } = require('next-i18next/rewrites');
const localeSubpaths = {
en: 'en', // <------
ru: 'ru',
};
module.exports = {
rewrites: async () => nextI18NextRewrites(localeSubpaths),
publicRuntimeConfig: {
localeSubpaths,
},
devIndicators: {
autoPrerender: false,
},
};
What is the best way to use Pa11y with Supertest? Something like:
describe ('my page', function () {
it ('is accessible', function () {
request (server).get ('/').expect (function ({ body }) {
// How to run Pa11y here?
});
});
})
I would suggest not using supertest at all for these accessibility test as pa11y can ping url's directly.
const pa11y = require('pa11y');
const request = require('supertest');
const mocha = require('mocha');
const { expect } = require('chai');
const server = require('./server');
const url =
process.env.NODE_ENV === 'testing'
? 'http://localhost:3000'
: 'http://example.com';
describe('my page', function() {
it('is accessible', function(done) {
pa11y(`${url}/`, function(err, results) {
expect(results.issues).to.be.empty;
done();
});
});
});