run vue3 ssr on cloudflare workers - vue.js

I'm trying to run a vue ssr app on cloudflare workers.
I generated a new project using wrangler generate test
I installed vue using npm install vue#next and npm install #vue/server-renderer
I edited the index.js file like this:
const { createSSRApp } = require('vue')
const { renderToString } = require('#vue/server-renderer')
const app = createSSRApp({
data: () => ({ msg: 'hello' }),
template: `<div>{{ msg }}</div>`
})
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
const html = await renderToString(app)
return new Response(html, {status: 200})
}
I then used wrangler dev to test it, but when I access the page I get this error:
ReferenceError: __VUE_PROD_DEVTOOLS__ is not defined
at Module.<anonymous> (worker.js:8:104768)
at n (worker.js:1:110)
at Object.<anonymous> (worker.js:8:104943)
at n (worker.js:1:110)
at worker.js:1:902
at worker.js:1:912
Any help or guidance is appreciated

I faced similar issue and was able to fix it by defining a global constant (VUE_PROD_DEVTOOLS = false) during compile time.
Here is how my webpack prod config looks like:
const webpack = require('webpack');
const { merge } = require("webpack-merge");
const webpackCommon = require("./webpack.common");
const prodConfig = {
mode: 'production',
plugins: [
new webpack.DefinePlugin({
__VUE_PROD_DEVTOOLS__: JSON.stringify(false)
}),
]
};
module.exports = merge(webpackCommon, prodConfig);

Related

React native couldn't resolve local module after noHoist has been added to project

I have this monorepo js setup with yarn workspaces and lerna
/package.json
/packages
/common (js shared code)
/package.json
/mobile (react native - metro)
/package.json
/web (CRA)
/package.json
Mobile and web packages are importing common package inside package.json as follow
"dependencies": {
"common": "*",
}
I had to add noHoist option in root package.json so that mobile native dependencies don't get hoisted so build scripts still run fine
"workspaces": {
"packages": [
"packages/*"
],
"nohoist": [
"**/react-native",
"**/react-native/**"
]
}
Web did work fine before and after adding noHoist option
React native metro bundling start failing after adding noHoist .. it shows
"Error: Unable to resolve module .. could not be found within the project or in these directories:
node_modules
../../node_modules"
However common package does actually exists under root node_modules ?
Looks like some kind of a linking issue ! (did try to link it manually/ same issue) .. note that I didn't add common package under noHoist
here how my metro config looks like
const path= require('path');
const watchFolders = [
path.resolve(`${__dirname}`), // Relative path to package node_modules
path.resolve(`${__dirname}/../../node_modules`), // Relative path to root node_modules ];
module.exports = {
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),},
maxWorkers: 2,
watchFolders, };
ANY IDEA ? 🧐
Turns out the issue was in bundling, fixed by editing metro.config.js to include blocklist and extraNodeModules
const path = require('path');
const exclusionList = require('metro-config/src/defaults/exclusionList');
const getWorkspaces = require('get-yarn-workspaces');
function generateAssetsPath(depth, subpath) {
return `/assets`.concat(
Array.from({ length: depth })
// eslint-disable-next-line no-unused-vars
.map((_, i) => `/${subpath}`)
.join(''),
);
}
function getMetroAndroidAssetsResolutionFix(params = {}) {
const { depth = 3 } = params;
let publicPath = generateAssetsPath(depth, 'dir');
const applyMiddleware = (middleware) => (req, res, next) => {
// eslint-disable-next-line no-plusplus
for (let currentDepth = depth; currentDepth >= 0; currentDepth--) {
const pathToReplace = generateAssetsPath(currentDepth, 'dir');
const replacementPath = generateAssetsPath(depth - currentDepth, '..');
if (currentDepth === depth) {
publicPath = pathToReplace;
}
if (req.url.startsWith(pathToReplace)) {
req.url = req.url.replace(pathToReplace, replacementPath);
break;
}
}
return middleware(req, res, next);
};
return {
publicPath,
applyMiddleware,
};
}
function getNohoistedPackages() {
// eslint-disable-next-line global-require
const monorepoRootPackageJson = require('../../package.json');
const nohoistedPackages = monorepoRootPackageJson.workspaces.nohoist
.filter((packageNameGlob) => !packageNameGlob.endsWith('**'))
.map((packageNameGlob) => packageNameGlob.substring(3));
return nohoistedPackages;
}
function getMetroNohoistSettings({
dir,
workspaceName,
reactNativeAlias,
} = {}) {
const nohoistedPackages = getNohoistedPackages();
const blockList = [];
const extraNodeModules = {};
nohoistedPackages.forEach((packageName) => {
extraNodeModules[packageName] =
reactNativeAlias && packageName === 'react-native'
? path.resolve(dir, `./node_modules/${reactNativeAlias}`)
: path.resolve(dir, `./node_modules/${packageName}`);
const regexSafePackageName = packageName.replace('/', '\\/');
blockList.push(
new RegExp(
`^((?!${workspaceName}).)*\\/node_modules\\/${regexSafePackageName}\\/.*$`,
),
);
});
return { extraNodeModules, blockList };
}
const workspaces = getWorkspaces(__dirname);
const androidAssetsResolutionFix = getMetroAndroidAssetsResolutionFix({
depth: 3,
});
const nohoistSettings = getMetroNohoistSettings({
dir: __dirname,
workspaceName: 'mobile',
});
module.exports = {
transformer: {
// Apply the Android assets resolution fix to the public path...
// publicPath: androidAssetsResolutionFix.publicPath,
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),
},
// server: {
// // ...and to the server middleware.
// enhanceMiddleware: (middleware) =>
// androidAssetsResolutionFix.applyMiddleware(middleware),
// },
// Add additional Yarn workspace package roots to the module map.
// This allows importing importing from all the project's packages.
watchFolders: [
path.resolve(__dirname, '../../node_modules'),
...workspaces.filter((workspaceDir) => !(workspaceDir === __dirname)),
],
maxWorkers: 2,
resolver: {
// Ensure we resolve nohoisted packages from this directory.
blockList: exclusionList(nohoistSettings.blockList),
extraNodeModules: nohoistSettings.extraNodeModules,
},
};
You can check this universal CRA/RN mono-repo that uses such metro configs

How to initialize manually next.js app (for testing purpose)?

I try to test my web services, hosted in my Next.js app and I have an error with not found Next.js configuration.
My web service are regular one, stored in the pages/api directory.
My API test fetches a constant ATTACKS_ENDPOINT thanks to this file:
/pages/api/tests/api.spec.js
import { ATTACKS_ENDPOINT } from "../config"
...
describe("endpoints", () => {
beforeAll(buildOptionsFetch)
it("should return all attacks for attacks endpoint", async () => {
const response = await fetch(API_URL + ATTACKS_ENDPOINT, headers)
config.js
import getConfig from "next/config"
const { publicRuntimeConfig } = getConfig()
export const API_URL = publicRuntimeConfig.API_URL
My next.config.js is present and is used properly by the app when started.
When the test is run, this error is thrown
TypeError: Cannot destructure property `publicRuntimeConfig` of 'undefined' or 'null'.
1 | import getConfig from "next/config"
2 |
> 3 | const { publicRuntimeConfig } = getConfig()
I looked for solutions and I found this issue which talks about _manually initialise__ next app.
How to do that, given that I don't test React component but API web service ?
I solved this problem by creating a jest.setup.js file and adding this line of code
First add jest.setup.js to jest.config.js file
// jest.config.js
module.exports = {
// Your config
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
};
AND then
// jest.setup.js
jest.mock('next/config', () => () => ({
publicRuntimeConfig: {
YOUR_PUBLIC_VARIABLE: 'value-of-env' // Change this line and copy your env
}
}))
OR
// jest.setup.js
import { setConfig } from 'next/config'
import config from './next.config'
// Make sure you can use "publicRuntimeConfig" within tests.
setConfig(config)
The problem I faced with testing with Jest was that next was not being initialized as expected. My solution was to mock the next module... You can try this:
/** #jest-environment node */
jest.mock('next');
import next from 'next';
next.mockReturnValue({
prepare: () => Promise.resolve(),
getRequestHandler: () => (req, res) => res.status(200),
getConfig: () => ({
publicRuntimeConfig: {} /* This is where you import the mock values */
})
});
Read about manual mocks here: https://jestjs.io/docs/en/manual-mocks
In my case, I had to:
Create a jest.setup.js file and
setConfig({
...config,
publicRuntimeConfig: {
BASE_PATH: '/',
SOME_KEY: 'your_value',
},
serverRuntimeConfig: {
YOUR_KEY: 'your_value',
},
});
Then add this in your jest.config.js file:
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],

How do you enable source maps in Webpack?

I want to enable source maps in my webpack.config.js. I'm adding onto some opensource and their webpack.config.js looks weird.
webpack.config.js
// Entry point webpack config that delegates to different environments depending on the --env passed in.
module.exports = function(env) {
process.env.NODE_ENV = env;
return require(`./webpack.${env}.js`);
};
Here is what it returns if env = development
/**
* Webpack configuration for development.
*
* Contains plugins and settings that make development a better experience.
*/
const webpack = require("webpack");
const merge = require("webpack-merge");
const fs = require("fs");
const { execSync } = require("child_process");
const path = require("path");
const argv = require("yargs").argv;
const commonConfig = require("./webpack.common.js");
const DashboardPlugin = require("webpack-dashboard/plugin");
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
if (!fs.existsSync(path.resolve(__dirname, "vendor", "vendor-manifest.json"))) {
// This _should_ exist, since we run the command for you when you run `npm run dev`
console.log(
"Vendor files not found. Running 'npm run build:dev-dll' for you..."
);
execSync("npm run build:dev-dll");
console.log("Done generating vendor files.");
}
const devConfig = {
mode: "development",
main: {
devtool: "source-map",
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify("development")
}),
new webpack.DllReferencePlugin({
context: ".",
manifest: require("./vendor/vendor-manifest.json")
}),
new ForkTsCheckerWebpackPlugin({
tslint: true,
async: false,
silent: true
})
]
}
};
// Only enable the dashboard plugin if --watch is specified
// The dashboard plugin annoyingly doesn't allow webpack to exit,
// so we only enable it with --watch, which doesn't exit anyways
if (argv.watch) {
devConfig.main.plugins.push(new DashboardPlugin());
}
module.exports = merge.multiple(commonConfig, devConfig);
I don't know if source map should be added to webpack.config.js or maybe just the development version and I don't know how to add it cause these config files look odd to me.
The line... "devtool": "source-map" is correct, but it appears to be at the wrong depth.
Should be:
const devConfig = {
mode: "development",
devtool: "source-map",
main: {
...
}
};

How do i install spectron and start scripting on it?

Got a recent Requirement, where i need to do Test Automation of Backend Node js application using the spectron. I would like to know what are programming skills required to approach the same
Find the Spectron documentation at https://electronjs.org/spectron
Installation
npm install --save-dev spectron
Sample test file looks like this
const Application = require('spectron').Application
const assert = require('assert')
const electronPath = require('electron')
const path = require('path')
describe('Application launch', function () {
this.timeout(10000)
beforeEach(function () {
this.app = new Application({
path: electronPath,
args: [path.join(__dirname, '..')]
})
return this.app.start()
})
afterEach(function () {
if (this.app && this.app.isRunning()) {
return this.app.stop()
}
})
it('shows an initial window', function () {
return this.app.client.getWindowCount().then(function (count) {
assert.equal(count, 1)
})
})
})
Spectron can work with any test framework. I prefer using mocha.
Clone this project for more info https://github.com/electron/spectron

how to automate electron exe file using protractor framework

Please tell me in detail ..
I have an electron application and I have exe of that .. but want to automate using protractor framework.
Guide me in that .
You should try using Spectron
https://electronjs.org/spectron
Spectron is a testing tool for electron application. You can test it after packing into a exe file or straight away starting the test by mentioning the main.js
npm install --save-dev spectron
Install spectron via npm . Below example uses mocha for assertions.
To get up and running from your command line:
Install mocha locally as a dev dependency.
npm i mocha -D
create a spec file like below
const Application = require('spectron').Application
const assert = require('assert')
const electronPath = require('electron')
const path = require('path')
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
global.before(() => {
chai.should();
chai.use(chaiAsPromised);
});
describe('Application launch', function () {
this.timeout(10000)
beforeEach(function () {
const opts = {
path: './your.exe'
};
const app = new Application(opts);
return app.start().then((app) => {
chaiAsPromised.transferPromiseness = app.transferPromiseness;
return app;
})
})
afterEach(function () {
if (this.app && this.app.isRunning()) {
return this.app.stop()
}
})
it('shows an initial window', function () {
return this.app.client.getWindowCount().then(function (count) {
assert.equal(count, 1)
// Please note that getWindowCount() will return 2 if `dev tools` are opened.
// assert.equal(count, 2)
})
})
})
Run the test by:
mocha spec.js