Serve static javascript file from nextjs api - file

I need a route in website build with nextjs that sends javascript that can be used on different website to do some things.
I created new file in pages/api, let's call it sendTest.ts so it's location is pages/api/sendTest.ts. In the same folder I crated test.ts file that I want to send from sendTest.ts.
sendTest.ts
import type { NextApiRequest, NextApiResponse } from 'next'
import fs from 'fs';
import path from 'path'
const filePath = path.join(__dirname, 'test.js');
const file = fs.readFileSync(filePath);
export default function handler(
req: NextApiRequest,
res: NextApiResponse
) {
res.setHeader('Content-Type', 'text/javascript');
res.status(200).send(file)
}
test.ts
console.log('hello');
After build nextjs serves that file at website.com/api/sendTest but after bundling it ends up as
"use strict";
(() => {
var exports = {};
exports.id = 318;
exports.ids = [318];
exports.modules = {
/***/ 211:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
console.log("hello there");
/***/ })
};
;
// load runtime
var __webpack_require__ = require("../../webpack-api-runtime.js");
__webpack_require__.C(exports);
var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))
var __webpack_exports__ = (__webpack_exec__(211));
module.exports = __webpack_exports__;
})();
which when used in different page as
<script src="website.com/api/sendTest"></script>
results in error
Uncaught ReferenceError: require is not defined
at sendTest:22:27
at sendTest:28:3
My question is how can I force nextjs to skip loading webpack into that file and just allow typescript to change content into javascript and serve file as is? Or is there better way to do what I want, which is sending javascript from specified nextjs route?

Got it.
I changed
const filePath = path.join(__dirname, 'test.js');
to
const filePath = path.resolve('.', 'script/test.js');
and put my script file into folder called script (name doesn't matter) in the main directory

Related

How to list all pages in a path?

I have a structure like this:
pages:
- route1
- lots of js page
- index.js
I would like to display a list of all pages under route1 on my index page.
How can I fetch all available pages?
I tried to use getStaticProps in index to load all the files using fs and path but I am not able to require all the pages.
export async function fetchPages() {
const fs = require('fs')
const path = require('path')
const files = fs.readdirSync(path.join(process.cwd(), '/pages/route1/'))
return map(files, (f) => {
return require(path.join(process.cwd(), '/pages/route1/', f))
})
}
but this is not working.
Edit: require is used to load all the export from those pages such as title of the page or excerpt to display on the index page.
Edit: The error is Error: Cannot find module '/path/to/pages/route1/pageName.js'. Coming from the require.
Edit: I tried to use How to generate a menu based on the files in the pages directory in Next.js but it does not work since in the next config file we have to use require/module.export but the require('path/to/page') is going to bring react pages with imports and exports
Can you create a page variable as an Array and push routes ?
const fs = require('fs')
const path = require('path')
const pages = []
const files = fs.readdirSync(path.join(process.cwd(), '/pages/route1/'))
files.forEach((file) => {
pages.push(require(path.join(process.cwd(), '/pages/route1/', file)))
})
return pages

Importing functions from other files not working (React)

Import:
import { get, set, faviconChange } from '/js/title.js';
title.js
var geta = a => localStorage.getItem(a)
var seta = (a, b) => localStorage.setItem(a, b)
export function get(a) {
localStorage.getItem(a);
}
export function set(a,b) {
localStorage.setItem(a,b);
}
document.title = get('title') || 'Anonymous'
var link = document.createElement('link');
link.rel = 'icon';
document.getElementsByTagName('head')[0].appendChild(link);
export function faviconChange(value) {
set('link', value)
link.href = get('link') || '/favicon.ico';
console.log("working " + link.href)
}
link.href = get('link') || '/favicon.ico';
Error:
./pages/index.js:6:0
Module not found: Can't resolve '/js/title.js'
4 | import Particles from 'react-tsparticles';
5 | import { loadFull } from "tsparticles";
> 6 | import { get, set, faviconChange } from '/js/title.js';
7 |
8 |
9 | export default function Home() {
https://nextjs.org/docs/messages/module-not-found
Whenever I try and import these functions, I get the above error and I've looked it up, and everyone seems to do it this way, yet I get an error. Am I missing something/putting these imports in the wrong file?
Try to import from './js/title.js';
When importing from another file, you must go up in the files hierarchy with a dot './'
3 suggestions are here.
1. adding export in your importing file
export default YourFunctionName;
2. As #SaF mentioned, make sure the path is correct
How?
If you are using linux/unix/mac use the command tree on the parent folder to get the exact path (if windows, you can install tree)
try using ../../../folder_x to go to folder_x which is 3 folders behind and ./ to get current folder
try printing your js file's absolute path using fs module https://www.npmjs.com/package/fs-js (comment the import line and try this)
3. Change jsx file extention to normal js
and add below code in webpack.config.js to resolve jsx as js
module.exports = {
//...
resolve: {
extensions: ['.js', '.jsx']
}
};

Accessing file in public folder through capacitor

I'm using ionic-v5, capactior and react to build an app.
I have a file (data.json) stored inside of my public/ folder.
I simply want to be able to load that file in and store it as an object.
So far I have tried:
import { Filesystem, FilesystemEncoding } from '#capacitor/core'
let contents = await Filesystem.readFile({
path: "data.json",
encoding: FilesystemEncoding.UTF8,
})
import { HTTP } from '#ionic-native/http';
let response = await HTTP.get("file://data.json", {}, {});
ret = response.data;
return ret;
I have also looked at https://ionicframework.com/docs/native/file but the documentation is poor to say the least.
Along with this I have tried pre-pending /android_asset/public to all of the paths but no luck (I know it would only work on Android, I just wanted to get something).
If you're using Ionic React (v5) and you just want to access a file in /myapp/public, you don't need Capacitor.
You can use axios (or fetch).
Folder structure:
/myapp
/assets
/json
/myFile.json
Sample code:
// https://stackoverflow.com/a/52570060
export const fetchJsonFile = (fileName: string): Promise<any> => (
axios.get(`./json/${fileName}`)
.then((response) => response).catch((error) => {
Promise.reject(error);
})
);

Failed to regiester service worker error in Next.js file

I'm using workbox-webpack-plugin to generate a service worker for me and I'm using copy-webpack-plugin move generated service worker files to the same directory as main.js. My next js config file goes like this:-
module.exports = {
webpack: (config, {isServer, buildId, dev, ...rest}) => {
if (dev) {
const devSwSrc = join(__dirname, "register-sw.js");
config.plugins.push(new CopyWebpackPlugin([devSwSrc]));
config.plugins.push(new GenerateSW({ ...defaultGenerateOpts }));
// Register SW
const originalEntry = config.entry;
config.entry = async () => {
const entries = await originalEntry();
const swCompiledPath = join(__dirname, 'register-sw-compiled.js');
if (entries['main.js'] && !entries['main.js'].includes(swCompiledPath)) {
let content = await readFile(require.resolve('./register-sw.js'), 'utf8');
await writeFile(swCompiledPath, content, 'utf8');
entries['main.js'].unshift(swCompiledPath);
}
return entries;
};
}
I'm trying to copying my service worker to the same dir as main.js which is chunk/static so that when it's fetched it should not return any error. But instead, I'm getting this error.
TypeError: Failed to register a ServiceWorker for scope ('[http://localhost:3000/](http://localhost:3000/)') with the script ('[http://localhost:3000/service-worker.js](http://localhost:3000/service-worker.js)'): A bad HTTP response code (404) was received when fetching the script.
I know this error is because it's not getting served from the same dir as main.js and I need to make some changes in copy-webpack-plugin in order to achieve that. Also I'm trying to avoid custom server.js file to server routes like /service-worker
Any help would be really appreciated. Thanks in advance

create react app Configuration file after build app

I want a Config File (JSON) in root folder after build to config my app.
like Translation and API Urls and ...
Can I do this with create react app?
Create config.js or json file outside src directory and include it in index.html like
<script src="%PUBLIC_URL%/config.js" type="text/javascript"></script>
configure parameters in config.js
config.js
var BASE_URL = "http://YOUR-URL";
you can get paramenters like
const BASE_URL = window.BASE_URL;
You can store you JSON file in the public/ folder and it'll automatically provide this file when you host your Create React App.
Something like: /public/my-configuration-file.json
then when you restart your application:
localhost:3000/my-configuration-file.json
will provide you this json file.
You could create a custom hook that reads a "public" config file using fetch.
// This path is relative to root, e.g. http://localhost/config.json
const configFile = './config.json'
export function useConfig() {
const [config, setConfig] = useState(initialConfig);
useEffect(() => {
(async function fetchConfig() {
try {
const response = await (await fetch(configFile)).json();
setConfig(response);
} catch (e) {
console.log(e);
}
}());
}, []);
return config;
}
Then use it anywhere in you app
function App() {
const config = useConfig();
return (
<div>{config.foo}</div>
);
}
You'll always have an up to date non-cached version of it's data.
updating this topic with a brand new package that is available now that brings the joys of .Net Configuration to the JavaScript world: wj-config.
This package is pretty much an exact answer to what you need. Read this blog post for more information.
It is incredible to me how during over 6 years nobody filled in this gap in React (and JavaScript in general). Anyway, give wj-config a try. I think it will be a positive experience.

Resources