Does Next.js 11.0.0 support barrel(index) files? - next.js

Barrel/index files seem to create issues when used with next.js. It doesn't seem established if it's purely a webpack issue or both webpack and next.js
According to this issue tree shaking stops working if we use barrel files. I also created a small repo where I have an issue with an index file. Not sure if it's a tree shaking issue.
Steps to reproduce the issue:
npm install
npm run dev
in browser, visit http://localhost:3000/about-pro, expect to see blank page with errors or warnings in browser's console
go to server's console(where you run npm run dev)
see an error of sort "Module not found: Can't resolve 'fs'" (1) (2) (3)
1- this comes from the await serialize in getAboutPageData file. Which itself is only called within getStaticProps
2 - googling for this issue, you'll find solutions such as modifying next.config.js file. It still doesn't work. Feel free to uncomment the next.config.js file and see for yourself
3 - to "solve" the issue, go to about-pro.tsx, in the imports, import AboutPage from its own file instead of from the barrel/index file
If I only import getAboutPageData from the barrel/index file, then it works fine. But as soon as I import e.g. AboutPage from it, it starts throwing unrelated issues.
Can I continue using barrel/index files with next.js and if yes, is there a simple and intuitive way to do that?

The issue is not in the barrel files themselves but in the library that you're using combined with barrel files.
If you take a look at the readme file https://github.com/hashicorp/next-mdx-remote#examples you can find a warning:
IMPORTANT: Be very careful about putting any mdx-remote code into a separate "utilities" file. Doing so will likely cause issues with nextjs' code splitting abilities - it must be able to cleanly determine what is used only on the server side and what should be left in the client bundle. If you put mdx-remote code into an external utilities file and something is broken, remove it and start from the simple example above before filing an issue.
So in order to make your code work you need to remove the export of getAboutPageData from your barrel file, like this:
export { default as AboutPage } from './AboutPage';
// export { default as getAboutPageData } from './getAboutPageData';
and move the code that uses the library inside the about-pro.tsx file.
import { AboutPage } from '../modules/about';
import { serialize } from 'next-mdx-remote/serialize';
const AboutPro = (props) => {
return <AboutPage {...props} />;
};
export const getStaticProps = async () => {
const serializedContent = await serialize(`# Header1`);
const data = serializedContent;
return { props: {} };
};
export default AboutPro;
I think the issue is that the modules imported in barrel files are executed both client and server side. Probably removing side effects from the barrel file could solve the issue, but I don't know enough about Next.js to be able to do it correctly.

Related

Linking Google credentials to vercel

I did my best to figure this one out by myself, but I'm totally missing something.
I'm using NextJS 12 and Google Cloud Translate's API to convert a word on a button. Locally it works fine, but once I try to deploy to vercel the permissions/keys gets messed up somewhere.
Locally I have my key.json, which I got from my service account. It's just in my project's root. I have my .env.local file that has references that key file. It looks like this
GOOGLE_APPLICATION_CREDENTIALS=./<projectid&key>.json
But when I try to translate, I get hit with an error.
'Request failed with status code 500'
My translate endpoint looks like this, which I pretty much copied from Google's small tutorial.
import { NextApiRequest, NextApiResponse } from "next";
export default async (req: NextApiRequest, res: NextApiResponse) => {
const translationClient = new TranslationServiceClient();
const projectId = <myprojectID>;
const location = "global";
async function translateText() {
const request = {
parent: `projects/${projectId}/locations/${location}`,
contents: [req.body.text],
mimeType: "text/plain",
sourceLanguageCode: "en",
targetLanguageCode: "es",
};
const [response] = await translationClient.translateText(request);
res.json(response.translations[0].translatedText);
}
translateText();
};
Things I've tried
Putting the JSON as one single environmental variable on vercel. So It was basically GOOGLE_APPLICATION_CREDENTIALS and the key.json file.
Tried putting it all in one line.
Tried taking the keys apart and putting it into a format like this:
GOOGLE_ACCOUNT_TYPE=service_account
GOOGLE_PROJECT_ID=project11111
GOOGLE_PRIVATE_KEY_ID=11111111111111
etc
However I wasn't about to get this method working locally either.
4. Kept the .env.local's path to key.json and just uploaded the key.json itself.
None of these worked and I'm pretty lost.
Resources I've looked at
https://github.com/vercel/vercel/issues/749#issuecomment-715009494
Escaping issue with firebase privateKey as a Heroku config variable
https://daveteu.medium.com/call-google-cloud-function-from-vercel-serverless-hosting-1b1688bb462c
I've tried to apply these to my situation, but I couldn't figure it out. I'd really appreciate any help! Thank you so much.
After looking around for a few days, I found a solution that worked.
I turned my keys.json into a base64 string using a similar command.
https://gist.github.com/tomi/0675e58919af4554b198cee3f84405e5
Then used the method found here.
https://github.com/orgs/vercel/discussions/219
I put that base64 string into one line in my .env file to check and then did the same for Vercel environmental variables, and it worked.

How to "package" other resources with deno

In deno you can load related modules or other code by just referencing the relative path to those ES6 modules. Deno will handle loading them appropriately. What's the way to do this for non-es6 modules? For example: say I wanted to include some custom css with my deno project? Deno doesn't allow doing import mycss from "./relative.css";.
Deno file operations do work for local files, but they're evaluated relative to the cwd not the current file, and they don't work for arbitrary URLs. fetch, on the other hand, should be perfect, but currently doesn't support file schemes and the decision isn't being actively considered. Combining these yields the only solution I can come up with, but I really don't like it:
async function loadLocal(relative: string): Promise<string> {
const url = new URL(relative, import.meta.url);
if (url.protocol === 'file:') {
return await Deno.readTextFile(url.pathname);
} else {
const resp = await fetch(url.href);
return await resp.text();
}
}
This seems like it should mostly work, but it seems like a terrible way to hack in something that I expected would be supported by design in deno. It also must be redeclared in each file, or have the callers URL passed in, although there might be a way to avoid that. It doesn't work on windows without modifying the path delimiter.
Update
Deno.emit seems close to what I would want, however for some reason it has different behavior than standard importing:
If the rootSpecifier is a relative path, then the current working directory of the Deno process will be used to resolve the specifier. (Not relative to the current module!)
It also still requires that the paths be to valid modules, instead of arbitrary text.
As #Zwiers pointed out, deno 1.6 now supports fetch with the file protocol, so this is now irrelevant.

Install fonts on angular 2 page

I have an Angular 2 application in which i wish to use wrapbootstrap. I do however have a problem with the fonts (bootstrap, font-awesome, google) as i do not know how to implement them.
When using the css file for wrapbootstrap is says it cannot find font awesome:
"Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost:8000/fonts/font-awesome/fontawesome-webfont.woff2?v=4.4.0"
I cannot make sense of this as i can see the missing file(s) in resources in the chrome console on that exact address.
The font files are currently in a folder vi the following relative path from the css (application.css) file using them:
Which fits the required path in the css file:
I hope someone out there can provide some guidance as i am lost.
Thanks in advance
Solved
the problem was apparently the location of my fonts folder.
my file structure are as follows:
and i had firstly added the fonts/ relative to where the application.css file was. It had to be located in the root of my app (src)
Adding fonts installed with package manager is quite often a task. For instance, using font-awesome or any other similar library is a typical task one will need.
For this purpose, you can go through the following steps:
In tools/config/project.config.ts:
...
export class ProjectConfig extends SeedConfig {
PROJECT_TASKS_DIR = join(process.cwd(), this.TOOLS_DIR, 'tasks', 'project');
FONTS_DEST = `${this.APP_DEST}/fonts`;
FONTS_SRC = [
'node_modules/bootstrap/dist/fonts/**'
];
...
Create a file tools/tasks/project/build.fonts.ts:
import * as gulp from 'gulp';
import Config from '../../config';
export = () => {
return gulp.src(Config.FONTS_SRC)
.pipe(gulp.dest(Config.FONTS_DEST));
};
In gulpfile.ts (or in seed.tasks.json for newer versions of the Seed)
// Build dev.
gulp.task('build.dev', done =>
runSequence('clean.dev',
'tslint',
'build.assets.dev',
'build.fonts', // Added task;
'build.js.dev',
'build.index.dev',
done));
// Build prod.
gulp.task('build.prod', done =>
runSequence('clean.prod',
'tslint',
'build.assets.prod',
'build.fonts', // Added task;
'build.html_css.prod',
'build.js.prod',
'build.bundles',
'build.bundles.app',
'build.index.prod',
done));
// Build test.
gulp.task('build.test', done =>
runSequence('clean.dev',
'tslint',
'build.assets.dev',
'build.fonts', // Added task;
'build.js.test',
'build.index.dev',
done));
src

"Required module not found" for module that exists in node_modules

Some modules just seem to be invisible to Flow. For example I have react-native-overlay installed via npm into my node_modules directory but I get a whole bunch of errors like this from Flow:
[js/components/DatePickerOverlay.js:18
18: let Overlay = require('react-native-overlay');
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ react-native-overlay. Required module not found
This module doesn't have types so it would be fine if I could just get Flow to ignore it entirely.
Here's my .flowconfig (based on React Native's one):
https://gist.github.com/almost/20c6caf6d18d0e5c689f
As you can see I'm on flow 0.20.1 and I have module.system=haste (as required by React Native)
I tried adding a //$FlowIgnore comment to the import lines but then Flow complains about an unneeded ignore comment! I also tried creating a react-native-flow.js.flow file with a dummy export which seemed to work at first but then after a flow restart stopped working.
Any ideas for how to either help Flow find this module or make it ignore the import line completely?
Looks like you're ignoring it here: https://gist.github.com/almost/20c6caf6d18d0e5c689f#file-flowconfig-L42-L50
If you don't mind manually typing it up, add a react-native-overlay.js to your interfaces and type up a couple signatures.
This is happening because the library doesn't exist in flow-typed.
A simple fix could be creating the following entry in the .flowconfig file:
[ignore]
<PROJECT_ROOT>/libdefs.js
[libs]
./libdefs.js
If using flowtype < 0.60.0 add in libdefs.js
// #flow
declare module "react-native-overlay" {
declare var exports: any;
}
Or if using flowtype > 0.60.0
declare module 'react-native-overlay' {
declare module.exports: any;
}
Note: any is an unsafe type so you can always take advantage of improve the definition of the library
Hope that helps,

Cannot compile namespaces when the '--isolatedModules' flag is provided

I am using urigo:angular2-meteor. When I add an empty main.ts in server folder, it always shows:
Cannot compile namespaces when the '--isolatedModules' flag is
provided.
Even I added the code below on the top of main.ts, it still shows same thing.
/// <reference path="../typings/angular2-meteor.d.ts" />
I faced similar issue in react + ts. I had commented out all my code.
Turns out
A global file cannot be compiled using '--isolatedModules'. Ensure your file contains imports, exports, or an 'export {}' statement.
So, added something like:
export const foo = 'foo';
or
export {}
It's a temporary solution, else you can delete the file with commented code or update tsconfig.json
I had the same problem and I added tsconfig.json into the root directory of my project.
{
"compilerOptions": {
"isolatedModules": false
}
}
I didn't have the time to dive into it, but it solved the problem.
I was getting this error when file was not imported in any other file.
Importing it in any other file (import {} from "/the-filename-having-compilation-error"), removed this error.
I had the same problem. I was made a component and never use that. When I imported that component In one of my page and use that and RERUN the project again , error was disappear.
This error occurs mostly when working with React + TypeScript
Simplest Solution for the same is to add 'export' keyword before the class creation or export the class in the end using
export default className;
If you have eslint installed check the rules section in .eslintrc.json file for any contradicting action.If the action you perforned is against the rule defined then error appears.

Resources