Below are some options from an open-webpack (not CRA) react project:
// webpack.config.js
module.exports = {
// ...
entry: {
main: './src/index.js',
'editor.worker': 'monaco-editor/esm/vs/editor/editor.worker.js',
'yaml.worker': 'monaco-yaml/lib/esm/yaml.worker.js',
},
// ...
How to implement similar configuration in config-overrides.js (using react-app-rewired)?
// config-overrides.js
module.exports = function override (config) {
config.entry = // ???
return config
}
My experience:
Simply set it to:
config.entry = {
main: './src/index.js',
'editor.worker': 'monaco-editor/esm/vs/editor/editor.worker.js',
'yaml.worker': 'monaco-yaml/lib/esm/yaml.worker.js',
}
doesn't work. It even causes issues in loading index.js!
config.optimization.runtimeChunk = 'single'
maybe help you ...
https://webpack.js.org/configuration/optimization/#optimizationruntimechunk
Related
in my project i am using cypress with plain javascript. i am facing the challenge of importing the modules (page objects) via aliases instead of spaghetti code like ../../../../folder/page.js.
I don't use typescript or react.js and don't have a src folder/directory.
my tests run locally in the browser or via a docker image (pipeline).
I would like to transform from this:
import { LoginPage } from "../../pages/loginPage.js";
to something like this:
import { LoginPage } from "#Pages/loginPage.js";
but I always get an error:
Error: Webpack Compilation Error
./cypress/e2e/accountOverview/accountOverviewPageTest.spec.js
Module not found: Error: Can't resolve 'Pages/loginPage.js' in 'C:\Users\User\automated_frontend_tests\automated_frontend_tests\cypress\e2e\accountOverview'
resolve 'Pages/loginPage.js' in 'C:\Users\User\automated_frontend_tests\automated_frontend_tests\cypress\e2e\accountOverview'
Parsed request is a module
using description file: C:\Users\User\automated_frontend_tests\automated_frontend_tests\package.json (relative path: ./cypress/e2e/accountOverview)
Field 'browser' doesn't contain a valid alias configuration
Looked for and couldn't find the file at the following paths:
[C:\Users\User\automated_frontend_tests\automated_frontend_tests\cypress\e2e\accountOverview\node_modules]
[C:\Users\User\automated_frontend_tests\automated_frontend_tests\cypress\e2e\node_modules]
[C:\Users\User\automated_frontend_tests\automated_frontend_tests\cypress\node_modules]
[C:\Users\node_modules]
[C:\node_modules]
[C:\Users\User\automated_frontend_tests\automated_frontend_tests\node_modules\Pages\loginPage.js]
[C:\Users\User\automated_frontend_tests\node_modules\Pages\loginPage.js]
[C:\Users\User\node_modules\Pages\loginPage.js]
[C:\Users\User\automated_frontend_tests\automated_frontend_tests\node_modules\Pages\loginPage.js.js]
[C:\Users\User\automated_frontend_tests\node_modules\Pages\loginPage.js.js]
[C:\Users\User\node_modules\Pages\loginPage.js.js]
[C:\Users\User\automated_frontend_tests\automated_frontend_tests\node_modules\Pages\loginPage.js.json]
[C:\Users\User\automated_frontend_tests\node_modules\Pages\loginPage.js.json]
[C:\Users\User\node_modules\Pages\loginPage.js.json]
[C:\Users\User\automated_frontend_tests\automated_frontend_tests\node_modules\Pages\loginPage.js.jsx]
[C:\Users\User\automated_frontend_tests\node_modules\Pages\loginPage.js.jsx]
[C:\Users\User\node_modules\Pages\loginPage.js.jsx]
[C:\Users\User\automated_frontend_tests\automated_frontend_tests\node_modules\Pages\loginPage.js.mjs]
[C:\Users\User\automated_frontend_tests\node_modules\Pages\loginPage.js.mjs]
[C:\Users\User\node_modules\Pages\loginPage.js.mjs]
[C:\Users\User\automated_frontend_tests\automated_frontend_tests\node_modules\Pages\loginPage.js.coffee]
[C:\Users\User\automated_frontend_tests\node_modules\Pages\loginPage.js.coffee]
[C:\Users\User\node_modules\Pages\loginPage.js.coffee]
# ./cypress/e2e/accountOverview/accountOverviewPageTest.spec.js 5:17-46
I have tried several solutions, including:
//webpack.config.js
module.exports = {
resolve: {
alias: {
"#pages": path.resolve(__dirname, "cypress/pages/*"),
},
},
};
//testspec file
import { LoginPage } from "#pages/loginPage.js";
const loginPage = new LoginPage();
#Uzair Khan:
I tried your solution, but it still didn't work. The error message remains the same. It seems that the IDE does not search in the correct folder, but only in ...\node_modules\#page\loginPage.js which makes no sense.
If I enter const loginPage = new LoginPage(), the module LoginPage() cannot be found by the IDE either. Something is wrong with the solution. Do I still have to install any packages via NPM?
In your webpack.config.js file add resolve.alias which you want to make alias. It looks like something this below:
resolve: {
alias: {
'#page': path.resolve(__dirname, '{path you want to make alias}')
}
}
Since you are using cypress, you have to update the resolve path in cypress.config.js. Here is mine cypress.config.js
import { defineConfig } from 'cypress'
import webpack from '#cypress/webpack-preprocessor'
import preprocessor from '#badeball/cypress-cucumber-preprocessor'
import path from 'path'
export async function setupNodeEvents (on, config) {
// This is required for the preprocessor to be able to generate JSON reports after each run, and more,
await preprocessor.addCucumberPreprocessorPlugin(on, config)
on(
'file:preprocessor',
webpack({
webpackOptions: {
resolve: {
extensions: ['.ts', '.js', '.mjs'],
alias: {
'#page': path.resolve('cypress/support/pages/')
}
},
module: {
rules: [
{
test: /\.feature$/,
use: [
{
loader: '#badeball/cypress-cucumber-preprocessor/webpack',
options: config
}
]
}
]
}
}
})
)
// Make sure to return the config object as it might have been modified by the plugin.
return config
}
And import in other file via that alias you set in cypress.config.js. Here is mine for example:
import page from '#page/visit.js'
const visit = new page()
When('I visit duckduckgo.com', () => {
visit.page()
})
I think both answers are nearly there, this is what I have for src files:
const webpack = require('#cypress/webpack-preprocessor')
...
module.exports = defineConfig({
...
e2e: {
setupNodeEvents(on, config) {
...
// #src alias
const options = {
webpackOptions: {
resolve: {
alias: {
'#src': path.resolve(__dirname, './src')
},
},
},
watchOptions: {},
}
on('file:preprocessor', webpack(options))
...
path.resolve() resolves a relative path into an absolute one, so you need to start the 2nd param with ./ or ../.
Also, don't use wildcard * in the path, you just need a single folder that will be substituted for the alias in the import statement.
If in doubt, check the folder returned (in the terminal)
module.exports = defineConfig({
...
e2e: {
setupNodeEvents(on, config) {
const pagesFolder = path.resolve(__dirname, './cypress/pages')
console.log('pagesFolder', pagesFolder)
I'm using CRA with CRACO to add another entry file to webpack configuration.
Here is the code:
module.exports = {
webpack: {
configure: (webpackConfig, {paths}) => {
return {
...webpackConfig,
entry: {
main: paths.appIndexJs,
content: './src/chromeServices/DOMEvaluator.ts',
},
}
},
},
}
However I don't need this file to be injected into the HTML file, is that possible to do so?
It is very easy to do so. CRACO and ultimately CRA make use of html-webpack-plugin to generate your HTML file and add the required script tags. You will have to make use of chunk filtering to achieve this.
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
webpack: {
configure: (webpackConfig, {paths}) => {
// 1. Find instance of HTML Webpack plugin
const pluginInstance = webpackConfig.plugins.find(
webpackPlugin => webpackPlugin instanceof HtmlWebpackPlugin
);
// 2. Define the exclusion or inclusion
if (pluginInstance) {
pluginInstance.options.excludeChunks = ['content'];
// Or, alternately, use include only feature
// pluginInstance.options.chucks = ['main'];
}
return {
...webpackConfig,
entry: {
main: paths.appIndexJs,
content: './src/chromeServices/DOMEvaluator.ts',
},
}
},
},
};
I have been working in a project where I need to use the outputPath function from the file-loader, to emit files to different folders, but I had difficulties to understand and making it work.
Part of my code is as follows:
const path = require('path');
const webpack = require('webpack');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const fs = require('fs'); // fs stands for file system, it helps accessing phyisical file systems
const BRANDS = {
br1: 'br1.local',
b22: 'br2.local'
};
module.exports = {
mode: 'production',
entry: {
main: './src/js/main.js'
},
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/',
filename: 'build.js'
},
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]',
outputPath: (url, resourcePath, context) => {
if (/my-custom-image\.png/.test(resourcePath)) {
return `other_output_path/${url}`;
}
if (/images/.test(context)) {
return `image_output_path/${url}`;
}
return `output_path/${url}`;
}
}
},
]
},
documentation says that resourcePath is the absolute path to assets, I am not sure about this, as my assets folder has another name not assets, does it matter? it looks like: /src/images.
What is context not sure what is my context. When I do a console.log of these arguments it shows undefined, and it doesn't emit the images to the right folders.
You just need to add your folder name inside if statement.
If your folder tree looks like this:
/src/images/subfolder/
Change your code to this:
outputPath: (url, resourcePath) => {
if (/subfolder/.test(resourcePath)) {
return `images/subfolder/${url}`;
}
return `images/${url}`;
}
I am trying to pass data that I get from my module options down to a plugin. So let's say this is my module:
module.exports = function (moduleOptions) {
const options = {
...this.options.moduleName,
...moduleOptions
}
this.addPlugin({
src: resolve(__dirname, 'plugin.js'),
options
})
}
and this is my plugin
import { createStore } from 'lib';
export default async ({ store, app }) => {
const settings = {
axios: app.$axios,
models: <% options.models %>
}
settings.axios = app.$axios;
createStore(settings).install()(store)
};
and this is my config
const { resolve } = require('path')
module.exports = {
rootDir: resolve(__dirname, '..'),
buildDir: resolve(__dirname, '.nuxt'),
srcDir: __dirname,
render: {
resourceHints: false
},
modules: [
'moduleName'
],
moduleName: {
{ models: require(resolve(__dirname, '../example/models')) }
}
}
it throws
axios: app.$axios,
7 | models:
> 8 | }
where models is just empty, nothing behind it. No null, no undefined.
But if I do <% console.log(options.models) %> it will show the models that I've loaded. Btw models is just an array of classes.
These models must be configurable, so how do I pass these data from my nuxt.config.js via a module to my plugin?
Hope somebody knows :)
I've worked around this issue using an require in my plugin instead of my config.
I thought by exporting specific functions and use it will only include this function in a compiled file but it doesn't seem so ex:
file1:
export function redu1(state = null, action) {
return state;
}
export function redu2(state = null, action) {
return state;
}
file2:
import {redu1} from './file1';
What did i see in the compiled file that all the functions are included?
According to Webpack Tree Shaking, you should set property mode to production in your webpack.config.js file to remove dead code from bundle.
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
mode: 'production'
};