Path name in google cloud run for Piscina - node.js

I'm added Piscina to my Node JS server, locally it works but when I upload the file to google cloud run, it's taking the directory that I specify in my Dockerfile.
In node js I use:
const piscina = new Piscina({
filename: path.resolve("./") + '/workers/send_payment_by_mail_worker.js'
});
const result = piscina.runTask({_data: this.data});
In the index.js file I can use:
const piscina = new Piscina({
filename: path.resolve( __dirname + '/workers/send_payment_by_mail_worker.js')
});
Which prints out the correct location where the file is located.
In my dockerfile I have :
FROM node:12.18.1
WORKDIR /
COPY package.json package.json
COPY package-lock.json package-lock.json
RUN npm install
COPY . .
CMD [ "node", "index.js" ]
Google cloud run takes / as main directory. How do you need to configure that cloud run takes the correct file directory for location the file for Piscina?
The error that I receive is:
2020-11-27T07:56:31.726607ZError [ERR_MODULE_NOT_FOUND]: Cannot find module '/services/action/workers/send_payment_by_mail_worker.js' imported from /node_modules/piscina/dist/src/worker.js
Default
2020-11-27T07:56:31.726628Z at finalizeResolution (internal/modules/esm/resolve.js:284:11)
Default
2020-11-27T07:56:31.726636Z at moduleResolve (internal/modules/esm/resolve.js:665:10)
Default
2020-11-27T07:56:31.726642Z at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:755:11)
Default
2020-11-27T07:56:31.726648Z at Loader.resolve (internal/modules/esm/loader.js:97:40)
Default
2020-11-27T07:56:31.726654Z at Loader.getModuleJob (internal/modules/esm/loader.js:243:28)
Default
2020-11-27T07:56:31.726660Z at Loader.import (internal/modules/esm/loader.js:178:28)
Default
2020-11-27T07:56:31.726666Z at importModuleDynamically (internal/modules/cjs/loader.js:1081:27)
Default
2020-11-27T07:56:31.726671Z at exports.importModuleDynamicallyCallback (internal/process/esm_loader.js:37:14)
Default
2020-11-27T07:56:31.726678Z at eval (eval at getImportESM (/node_modules/piscina/dist/src/worker.js:37:27), <anonymous>:1:16)
Default
2020-11-27T07:56:31.726684Z at getHandler (/node_modules/piscina/dist/src/worker.js:58:39)
Default
2020-11-27T07:56:31.726919ZuncaughtException

Related

Vite: Including files in build output

This is a Vue 3 + Vuetify + TS + Vite + VSCode project.
I'm trying to bundle an XML file in the production build. Some transformation needs to be applied on the file before spitting it out. Found this Vite plug-in that can do transformations. But unfortunately, it doesn't seem to touch XML files in any way. If I put my XML file in public folder, it gets copied to the build output, but is not processed by the transformation plugin. If I put it in assets or somewhere else under src, it is simply ignored.
How can I ask Vite to include certain file(s) in the build output and pass it through transformation?
Note: Before I migrated the project to Vite, I was using Vue 2 and WebPack, where I could use the well-known CopyWebpackPlugin to perform this transformation. Haven't been able to find locate its Vite equivalent till now.
You may want to just write a script to do the transformation and add it to your npm scripts. I created a simple chrome extension to play around with VITE. Having multiple html files was pretty simple:
import { defineConfig, BuildOptions } from 'vite'
import vue from '#vitejs/plugin-vue'
const { resolve } = require('path')
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
popup: resolve(__dirname, 'popup/index.html'),
options: resolve(__dirname, 'options/index.html'),
},
}
}
})
But I had to create a separate vite config file to process the background script since it had special configuration (didn't want hashing so I could specify the name in my manifest, esm module format), and it takes the typescript and outputs 'background.js' in the public folder:
import { defineConfig } from 'vite'
const { resolve } = require('path')
// https://vitejs.dev/config/
export default defineConfig({
build: {
emptyOutDir: false,
rollupOptions: {
input: resolve(__dirname, 'background.ts'),
output: {
format: "esm",
file: "public/background.js",
dir: null,
}
}
}
})
You could simply have the xml file in your src folder and run a special script (create a 'scripts' folder maybe) to do the transform and store the result in the public folder where vite will pick it up and copy it to the dist folder. Your 'build' script in package.json could look something like this:
"scripts": {
"build": "node scripts/transform-xml.mjs && vite build",
},
Author of the package has introduced a new option named replaceFiles in the version 2.0.1 using which you can specify the files that will be passed through the transform pipeline. I can now do the following in my vite.config.js to replace variables in my output manifest.xml file after build:
const replaceFiles = [resolve(join(__dirname, '/dist/manifest.xml'))];
return defineConfig({
...
plugins: [
vue(),
transformPlugin({
replaceFiles,
replace: {
VERSION_NUMBER: process.env.VITE_APP_VERSION,
SERVER_URL: process.env.VITE_SERVER_URL,
},
...
}),
...
});

My React App Unit Tests Jest is breaking: function(module,exports,require,__dirname,__filename,jest) Cannot use import statement outside a module

I'm facing a problem when trying to run the Jest tests (NextJs app) with my component library.
My React library
I'm using this command to build the React library:
"build-esm": "tsc --project tsconfig.build.json",
"build-cjs": "tsc --project tsconfig.build.json --module commonjs --outDir lib/cjs",
"build": "rm -fr lib/ && npm run build-esm && npm run build-cjs"
Will generate it:
package.json:
(...)
"main": "./lib/cjs/index.js",
"module": "./lib/esm/index.js",
"types": "./lib/esm/index.d.ts",
(...)
My "Nextjs client project" (that will use the lib as a dependency):
jest.config.js
// jest.config.js
const nextJest = require('next/jest');
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './'
});
// Add any custom config to be passed to Jest
/** #type {import('jest').Config} */
const customJestConfig = {
// Add more setup options before each test is run
setupFilesAfterEnv: ['./jest.setup.js'],
// if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
moduleDirectories: ['node_modules'],
testEnvironment: 'jest-environment-jsdom',
transformIgnorePatterns: ['<rootDir>/node_modules/']
};
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig);
console error:
(...)/node_modules/nanoid/index.browser.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import { urlAlphabet } from './url-alphabet/index.js'
^^^^^^
SyntaxError: Cannot use import statement outside a module
8 | var react_window_1 = require("react-window");
9 | var react_window_infinite_loader_1 = __importDefault(require("react-window-infinite-loader"));
> 10 | var nanoid_1 = require("nanoid");
I appreciate any support

Vite: Could not resolve entry module (index.html)

I am new to Openshift 3.11 deployment, I created a Multistage Dockerfile for a React application, the build want correctly on my local machine, but when I run on the openshift cluster I get the error below:
> kncare-ui#0.1.0 build
> tsc && vite build
vite v2.9.9 building for production...
✓ 0 modules transformed.
Could not resolve entry module (index.html).
error during build:
Error: Could not resolve entry module (index.html).
at error (/app/node_modules/rollup/dist/shared/rollup.js:198:30)
at ModuleLoader.loadEntryModule (/app/node_modules/rollup/dist/shared/rollup.js:22680:20)
at async Promise.all (index 0)
error: build error: running 'npm run build' failed with exit code 1
and this is my Dockefile
FROM node:16.14.2-alpine as build-stage
RUN mkdir -p /app/
WORKDIR /app/
RUN chmod -R 777 /app/
COPY package*.json /app/
COPY tsconfig.json /app/
COPY tsconfig.node.json /app/
RUN npm ci
COPY ./ /app/
RUN npm run build
FROM nginxinc/nginx-unprivileged
#FROM bitnami/nginx:latest
COPY --from=build-stage /app/dist/ /usr/share/nginx/html
#CMD ["nginx", "-g", "daemon off;"]
ENTRYPOINT ["nginx", "-g", "daemon off;"]
EXPOSE 80
Vite by default uses an html page as an entry point. So you either need to create one or if you don't have an html page you can use it in "Library Mode".
https://vitejs.dev/guide/build.html#library-mode
From the docs:
// vite.config.js
const path = require('path')
const { defineConfig } = require('vite')
module.exports = defineConfig({
build: {
lib: {
entry: path.resolve(__dirname, 'lib/main.js'),
name: 'MyLib',
fileName: (format) => `my-lib.${format}.js`
},
rollupOptions: {
// make sure to externalize deps that shouldn't be bundled
// into your library
external: ['vue'],
output: {
// Provide global variables to use in the UMD build
// for externalized deps
globals: {
vue: 'Vue'
}
}
}
}
})
If you're using ES Modules (i.e., import sytax):
Look in your package.json to confirm type field is set to module:
// vite.config.js
import * as path from 'path';
import { defineConfig } from "vite";
const config = defineConfig({
build: {
lib: {
entry: path.resolve(__dirname, 'lib/main.js'),
name: 'MyLib',
fileName: (format) => `my-lib.${format}.js`
},
rollupOptions: {
// make sure to externalize deps that shouldn't be bundled
// into your library
external: ['vue'],
output: {
// Provide global variables to use in the UMD build
// for externalized deps
globals: {
vue: 'Vue'
}
}
}
}
})
export default config;
Had same issue because of .dockerignore. Make sure your index.html not ignored.
In case if you ignoring everything (**) you can add !index.html to the next line and try.

import is not working nodeJs application React SSR

I'm trying to implement SSR for a React application I started with creating a server directory that contains 3 files (bootstrap, index, renderer)
bootstrap.js contains babel configs to transpile to es5
index.js create an express application and express Router
renderer.js is responsible for rendering React application to string and send it as html to client.
bootstap.js =>
require('ignore-styles');
require('#babel/register')({
ignore: [
function (filePath) {
return !filePath.includes('node_modules');
}
],
presets: [
[
"#babel/preset-env",
{
"modules": false
}
],
'#babel/preset-react',
'#babel/flow'
],
plugins: [
[
"#babel/plugin-transform-runtime",
{
"regenerator": true
}
],
"#babel/plugin-proposal-object-rest-spread",
"#babel/plugin-syntax-dynamic-import",
"react-loadable/babel",
"#babel/plugin-proposal-class-properties",
"dynamic-import-node"
]
});
require('./index');
index.js =>
import dotenv from 'dotenv';
import cookieParser from 'cookie-parser';
dotenv.config();
const express = require('express');
const serverRenderer = require('./middleware/renderer');
const PORT = process.NODE_ENV === 'development' ? 3000 : 7160;
const path = require('path');
const app = express();
app.use(cookieParser());
const router = express.Router();
const routes = require('../src/router/appRoutes').default;
router.use(express.static(
path.resolve(__dirname, '..', 'build'),
{ maxAge: '30d' },
));
routes.map(path => app.get(path, serverRenderer));
app.use(router);
app.listen(PORT, (error) => {
if (error) {
return console.log('something bad happened', error);
}
console.log("listening on " + PORT + "...");
});
but when I run
NODE_ENV=production node server/bootstrap.js
this command to start server side application I get this error
import dotenv from 'dotenv';
^^^^^^
SyntaxError: Unexpected identifier
at Module._compile (internal/modules/cjs/loader.js:723:23)
at Module._compile (/Users/amirtahani/projects/uneed/node_modules/pirates/lib/index.js:99:24)
at Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Object.newLoader [as .js] (/Users/amirtahani/projects/uneed/node_modules/pirates/lib/index.js:104:7)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
at Module.require (internal/modules/cjs/loader.js:692:17)
at require (internal/modules/cjs/helpers.js:25:18)
at Object.<anonymous> (/Users/amirtahani/projects/uneed/server/bootstrap.js:34:1)
and the weird thing is the same code is working on another project.
and here is my devDependencies
"devDependencies": {
"#babel/core": "7.6.4",
"#babel/plugin-proposal-class-properties": "7.5.5",
"#babel/plugin-proposal-object-rest-spread": "7.6.2",
"#babel/plugin-syntax-dynamic-import": "7.2.0",
"#babel/plugin-transform-classes": "7.5.5",
"#babel/plugin-transform-modules-commonjs": "7.6.0",
"#babel/plugin-transform-runtime": "7.6.2",
"#babel/preset-env": "7.6.3",
"#babel/preset-flow": "7.0.0",
"#babel/preset-react": "7.6.3",
"#babel/register": "7.6.2",
"babel-cli": "6.26.0",
"babel-plugin-dynamic-import-node": "2.3.0",
"babel-plugin-transform-es2015-modules-commonjs": "6.26.2",
"flow-bin": "0.102.0",
"ignore-styles": "5.0.1"
}
any ideas?
"import --from --" is ES15 syntax, however node.js uses commonJS module syntax. So you need to install and configure webpack. Babel just trans-piles the new generation javascript into the old javascript code. However webpack is going to bundle your application code into a single file and your server file will be executed through that bundle.js.
For server-side rendering you need 2 bundle.js. one for client and another one for server. HTML files without javascript have no functionality.
if we start from server, this is how we write our code into the index.js.
const renderToString=require("react-dom/server").renderToString //specifically created for server
const Home=require("./components/Home").default //home component
const React=require("react")
const express=require("express")
const app=express()
app.get("/",(req,res)=>{
const content =renderToString(<Home/>)
res.send(content)
})
This is how we render our code to the browser for "/" route. there are 2 flaws here. First one, we are sending file without javascript code. Any functionality in Home component will not work. For example, if you had button inside Home component with click event, that click event will not work. Because server is not shipping down any javascript code. Second flaw is we used jsx here:
const content =renderToString(<Home/>). so when node executes this file, it will not recognize this syntax and will give error.
to fix those 2 issues, we need webpack. webpack will transform index.js into a file which we specify the name and its location. In server-side, we usually name the file bundle.js inside public folder. So when we start the server with node or nodemon, we will execute public/bundle.js NOT the index.js file.
So we need to reorganize the code inside index.js and this time since webpack will transform the code, we can use "import" syntax.
import React from "react";
import { renderToString } from "react-dom/server";
import Home from "./components/Home"
import React from "react"
import express from "express";
const app=express()
app.use(express.static("public")) //This will make public folder publicly available so we can ship it down to the browser.
app.get("/",(req,res)=>{
const content=renderToString(<Home/>)
//I used template strings ``
const html= `
<html>
<head></head>
<body>
<div id="root">${content}</div>
<script src="bundle.js"> </script>
//since we are sending a file, express will look for bundle.js inside the public folder. So we do not need to write relative path or absolute path.
</body></html> `
res.send(html)
})
Now we need a file to configure webpack. We name it webpack.config.js in the root of the app.
const path=require("path")
module.exports={
//in server side we keep client and server logic inside src folder
entry:"./src/index.js", //relative path
mode:"development",
output:{filename:bundle.js,
path:path.resolve(__dirname,"build")},
//absolute path. that is why we use native node module path. also you do not need to create build folder. webpack will create automatically
module:{rules:[{test:/\.js$/,
loader:"babel-loader",
exclude:/node_modules/,
options:{presets:["#babel/preset-env","#babel/preset-react"]}}]}
}
lastly in package.json
"scripts": {
"dev:server": "nodemon --watch build --exec \"node build/bundle.js\"",
"dev:build-server": "webpack --config webpack.server.js --watch",
"dev:build-client": "webpack --config webpack.client.js --watch"
},
in dev:server we watch "build" folder for changes.(build folder is in the root of app.) then we execute "bundle.js" file inside the build directory.
so to give an answer to your question, this is the basic of server-side part of isomorphic javascript app.
I installed node LTS (v12.13.0) but got the same error when used import instead of require. It seems that es6 imports are still an experimental feature, even in the latest node version.
If you want to test this feature, you need to do these steps:
Add "type": "module" in your package.json
Run your server with this flag: --experimental-modules. e.g. NODE_ENV=production node --experimental-modules server/bootstrap.js
import and export syntax is still experimental in node js latest versions, but there is a work around to this issue.
try to add "type": "module" in your package.json file and change your .js bundle extension to .mjs in your webpack config and run your generated file with this command:
NODE_ENV=production node --experimental-modules server/bootstrap.mjs
also i recommend you to read this page.
First check if the dotenv package is installed or not. If not, you can install it in the following command -
npm i --save dotenv
In order to use dotenv, you don't need to import it and then configure it.
Instead use the following syntax -
require('dotenv').config()

Slack Integraton with Laravel Issues

I am trying to install slack node library, but not able to do it successfully.
I installed this library successfully on laravel 5.4 using node js. And my gulpfile is upgraded from 5.3 to 5.4 and attached below.
npm install #slack/client --save (Installation is fine but gukp is causing issue)
But when i run gulp command on shell i am getting following error:-
After adding adding this line in app.js:-
var RtmClient = require('#slack/client').RtmClient;
gulpfile.js (manually eddited)
const elixir = require('laravel-elixir');
const path = require('path');
const debug = require('gulp-debug');
const moment = require('moment');// in my gulp file
require('laravel-elixir-webpack-official');
require('laravel-elixir-vue-2');
elixir(function(mix) {
// Elixir.webpack.config.module.loaders = [];
Elixir.webpack.mergeConfig({
resolveLoader: {
root: path.join(__dirname, 'node_modules'),
},
module: {
loaders: [
{
test: /\.css$/,
loader: 'style!css'
}
]
}
});
mix.sass('app.scss')
.webpack('app.js')
.copy('node_modules/bootstrap-sass/assets/fonts/bootstrap/','public/fonts/bootstrap')
});
Error on Gulp Command
user1#console:/opt/lampp/htdocs/dev$ gulp
[15:40:27] Using gulpfile /opt/lampp/htdocs/dev/gulpfile.js
[15:40:27] Starting 'all'...
[15:40:27] Starting 'sass'...
[15:40:28] Finished 'sass' after 1.08 s
[15:40:28] Starting 'webpack'...
{ [Error: ./~/winston/package.json
Module parse failed: /opt/lampp/htdocs/dev/node_modules/winston/package.json Unexpected token (2:9)
You may need an appropriate loader to handle this file type.
| {
| "_args": [
| [
| {
# ./~/winston/lib/winston.js 14:18-44
# ./~/#slack/client/lib/helpers.js
# ./~/#slack/client/lib/clients/client.js
# ./~/#slack/client/lib/clients/web/client.js
# ./~/#slack/client/index.js
# ./resources/assets/js/app.js./~/winston/lib/winston/common.js
Module not found: Error: Can't resolve 'fs' in '/opt/lampp/htdocs/dev/node_modules/winston/lib/winston'
resolve 'fs' in '/opt/lampp/htdocs/dev/node_modules/winston/lib/winston'
Parsed request is a module
using description file: /opt/lampp/htdocs/dev/node_modules/winston/package.json (relative path: ./lib/winston)
Field 'browser' doesn't contain a valid alias configuration
after using description file: /opt/lampp/htdocs/dev/node_modules/winston/package.json (relative path: ./lib/winston)
resolve as module
/opt/lampp/htdocs/dev/node_modules/node_modules doesn't exist or is not a directory
Thanks in advance

Resources