How to resolve modules with turbopack in NextJS 13 - javascript

Node APIs are not available on the client, but many NextJS projects have nested dependencies to these APIs (i.e. fs). With webpack it's easy to adjust how the module resolves based on client/server environment, but it's unclear how to do so with turbopack.
Is there a turbopack workaround like the webpack one below?
webpack: (config, { isServer }) => {
if (!isServer) {
config.resolve.fallback.fs = false;
}
return config;
},

Related

writeToDisk with create-react-app not displaying work files

I am trying to configure webpack in my react app so that during development, the files are visible in the dist folder (or wherever).
So I tried react-app-rewired with the following config
module.exports = function override(config, env) {
config.devServer = {
devMiddleware: {
writeToDisk: true
}
}
return config;
}
But it doesn't seem to work. I've been looking for how to make writeToDisk work, and it seems to have changed at some point, because I can't find anything online that works.
How can I get writeToDisk to work so that it writes the hot-reload files to a visible folder when running react-scripts start?
I just ended up going with craco instead, which worked.
craco.config.js:
module.exports = {
devServer: (devServerConfig, { env, paths, proxy, allowedHost }) => {
devServerConfig.devMiddleware.writeToDisk = true;
return devServerConfig;
},
};

Output built dev files on Next.js project

I want Next.js to output built files so that local proxy can map them. How to let Next.js output dev files?
I once tried devServer.writeToDisk, but it didn't work because next.js doesn't use Webpack dev server.
// next.config.js
module.exports = {
webpack: (config) => {
config.devServer = { writeToDisk: true };
return config;
},
};

How do I Resolve an Alias with Node Sass in a .mjs Script?

My project's structure has a SCSS library for global settings and such, and main component scss modules are elsewhere with their corresponding component files. I have my Webpack set up to resolve a path alias # when it builds, so my usage of lines like #import "#/src/scss/variables/blah-blah.scss" works out just fine when running the project.
Conversely, I have some utility scripts i'm using to do SCSS benchmarking, just some compile and analyze operations to help illustrate our performance gains while we work on style changes. I have these built using the .mjs file extension, which I don't think is important here, it's just helping play nice with Typescript.
So when Node Sass encounters a path like #import "#/src/scss/variables/blah-blah.scss" it won't resolve the path. No surprise there, but I can't seem to locate a best solution to just help resolve the path within my script, rather than add on NPM packages to do a seemingly simple job. How should I be approaching this?
Error comes up from await sass.render()
import { writeFileSync } from "fs";
import sass from "node-sass";
import tildeImporter from "node-sass-tilde-importer";
import { resolve } from "path";
export const compileCSS = async module => {
const input = `src/components/${module}/scss/module.scss`;
const output = `stats/css/${module}.css`;
await sass.render(
{
file: resolve(input),
importer: tildeImporter,
outputStyle: "expanded",
outFile: resolve(output),
sourceMap: true
},
async function(error, result) {
if (error) {
await console.log(module, "COMPILE ERROR", error.message);
} else {
writeFileSync(resolve(output), result);
return result;
}
}
);
};
Further research shows me that Node Sass does not currently have a great way to enable this, though some ideas appear in the works.
I made a work around by converting my stats gathering operations into a Webpack loader module that analyzes and spits out my data in between steps to pack the compiled styles into the bundle. This way I get the alias path resolved and simplify the dev experience. It's a better solution than I had set out for so I'm pleased.

Setting environment variables in Gatsby

I used this tutorial: https://github.com/gatsbyjs/gatsby/blob/master/docs/docs/environment-variables.md
Steps I followed:
1) install dotenv#4.0.0
2) Create two files in root folder: ".env.development" and ".env.production"
3) "follow their setup instructions" (example on dotenv npm docs)
In gatsby-config.js:
const fs = require('fs');
const dotenv = require('dotenv');
const envConfig =
dotenv.parse(fs.readFileSync(`.env.${process.env.NODE_ENV}`));
for (var k in envConfig) {
process.env[k] = envConfig[k];
}
Unfortunately, when i run gatsby develop, NODE_ENV isn't set yet:
error Could not load gatsby-config
Error: ENOENT: no such file or directory, open 'E:\Front-End Projects\Gatsby\sebhewelt.com\.env.undefined'
It works when I set it manually:
dotenv.parse(fs.readFileSync(`.env.development`));
I need environment variables in gatsby-config because I put sensitive data in this file:
{
resolve: `gatsby-source-contentful`,
options: {
spaceId: envConfig.CONTENTFUL_SPACE_ID,
accessToken: envConfig.CONTENTFUL_ACCESS_TOKEN
}
}
How to make it work?
PS: Additional question - As this made me think, I know I shouldn't put passwords and tokens on github, but as netlify builds from github, is there other safe way?
I had a similar issue, I created 2 files in the root ".env.development" and ".env.production" but was still not able to access the env file variables - it was returning undefined in my gatsby-config.js file.
Got it working by npm installing dotenv and doing this:
1) When running gatsby develop process.env.NODE_ENV was returning undefined, but when running gatsby build it was returning 'production' so I define it here:
let env = process.env.NODE_ENV || 'development';
2) Then I used dotenv but specify the filepath based on the process.env.NODE_ENV
require('dotenv').config({path: `./.env.${env}`});
3) Then you can access your variables for your config:
module.exports = {
siteMetadata: {
title: `Gatsby Default Starter`,
},
plugins: [
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-source-contentful`,
options: {
spaceId: `${process.env.CONTENTFUL_ID}`,
accessToken: `${process.env.CONTENTFUL_TOKEN}`,
},
},
],
}
You should only use env files when you're comfortable checking those into git. For passwords/tokens/etc. add them to Netlify or whatever build tool you use through their dashboard.
These you can access in gatsby-config.js & gatsby-node.js via process.env.ENV_VARIABLE.
You can't access environment variables added this way in the browser however. For this you'll need to use .env.development & .env.production.
I really dislike the .env.production file pattern, our build system sets up and uses env variables and having extra build steps to write those into a file is weird. But Gatsby only whitelists GATSBY_ of the env vars, with no obvious way of adding your own.
But doing that isn't so hard, you can do it by adding something like this in the gatsby-node.js file:
exports.onCreateWebpackConfig = ({ actions, getConfig }) => {
const config = getConfig();
// Allow process.env.MY_WHITELIST_PREFIX_* environment variables
const definePlugin = config.plugins.find(p => p.definitions);
for (const [k, v] of Object.entries(process.env)) {
if (k.startsWith("MY_WHITELIST_PREFIX_")) {
definePlugin.definitions[`process.env.${k}`] = JSON.stringify(v);
}
}
actions.replaceWebpackConfig(config);
};
After doing a few searches, I found that we can set environment variables through netlify website, here are the steps:
Under your own netlify console platform, please go to settings
Choose build & deploy tab (can be found on sidebar)
Choose environment sub-tab option
Click edit variables and add/put your credentials in
Done!

Webpack breaking in IE11

It's difficult to track this down, so thanks for bearing with me. Some users were complaining that our site was broken in IE11. The app is using nextjs 3.0.1 and webpack 2.7.0.
Debugging in development mode
I think I have an issue similar to Angular RxJs timer pausing on IE11. I'm getting an error from a reference called webpack///webpack bootstrapxxxxxxxxxx (where the x's are some numbers in hex) in IE11.
Here's the function that's causing the issue:
// The require function
function __webpack_require__(moduleId) {
// Check if module is in cache
if(installedModules[moduleId]) {
return installedModules[moduleId].exports;
}
// Create a new module (and put it into the cache)
var module = installedModules[moduleId] = {
i: moduleId,
l: false,
exports: {},
hot: hotCreateModule(moduleId),
parents: (hotCurrentParentsTemp = hotCurrentParents, hotCurrentParents = [], hotCurrentParentsTemp),
children: []
};
// Execute the module function
var threw = true;
try {
modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
threw = false;
} finally {
if(threw) delete installedModules[moduleId];
}
// Flag the module as loaded
module.l = true;
// Return the exports of the module
return module.exports;
}
The line modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId)); throws the error Unable to get property 'call' of undefined or null reference.
I imagine this is due to a missing polyfill, so I followed the advice at https://github.com/zeit/next.js/issues/1254 and added this to next.config.js (the webpack config for next):
const originalEntry = config.entry
config.entry = function () {
return originalEntry()
.then((entry) => {
Object.keys(entry).forEach(k => {
entry[k].unshift('babel-polyfill')
})
console.log(entry)
return entry
})
}
I'm still seeing the same error.
Additional details in production
One thing that's interesting is that I have a different issue in the production version of the nextjs app. It's deep in the app.js file generated by next, but the error seems to come from this line https://github.com/ianstormtaylor/heroku-logger/blob/master/src/index.js#L12:
const {
LOG_LEVEL,
NODE_ENV,
} = process.env
It's throwing Expected identifier. Is this because the module isn't getting transpiled from ES6 to ES5 correctly? There's probably an underlying issue (that I saw in development), rather than a problem with the heroku-logger library.
Realize this is a complicated issue and I'm probably missing some details. Thanks in advance for your help!
In case anyone else wrestled with this, I left the babel-polyfill in the webpack config and changed the build command to:
next build && babel .next/*.js --out-dir . --presets=es2015,react
This is pretty clunky because some code is babel-ified by webpack and then again in the output directory. Would love other suggestions!

Categories

Resources