Multiple webpack alias configurations can't resolve modules - angularjs

I am working on an Angular 2 application written in Typescript, that is using webpack in conjunction with ts-loader to bundle everything together.
I am relying heavily on webpack's resolve.alias to cater for different build outputs and I have come across an issue.
When running a specific build, ts-loader is throwing an error saying it can not find a module that is used in the current build. This, I would assume, is due to the alias pointing to a different file.
eg:
file: myApp.ts
import {Logger} from 'logger';
export class myApp {}
I have two alias JSON files, one is setup to point 'logger' at remoteSystemLogger.ts, and another which points at consoleLogger.ts
Build A will use remoteSystemLogger,
Build B will use consoleLogger
Now each logger class will import their relative dependencies. For instance:
file: remoteSystemLogger.ts
import {HTTP} from 'http';
export class Logger {}
The problem is, that when I run build B, I am getting an error saying:
ERROR in remoteSystemLogger.ts
error TS2307: Cannot find module 'http'.
http as well as remoteSystemLogger is currently not specified in the alias JSON file for Build B, as Build B should have no dependency on it.
The alias file that get's used for the webpack build is determined at build time via a param.
Here is an example of the resolve used in webpack config
let moduleAliasingConfig = `./alias/${buildType}.json`
// ....
resolve: {
root: [
path.resolve('.'),
path.resolve('node_modules')
],
alias: moduleAliasingConfig,
extensions: ['', '.ts', '.js']
},
And here is the ts-loader config:
loaders: [
{test: /\.ts$/, loaders: ['ts'], exclude: [/\.(spec|e2e)\.ts$/]}
]
I am not sure if maybe I have miss-configured something, or this is an issue with either the loader, webpack's resolver, or just my understanding of how the aliasing works.
As my understanding is, that webpack will traverse through my import/dependency tree, based on the alias file and my entry point.
Additional env info:
package.json setup:
"ts-loader": "^1.2.1",
"webpack": "^1.13.0"

Related

Storybook webpack config not working - trying to run Storybook out of separate local project than components

I have a mature CRA-based React app running with Webpack 5. I would like to have a separate project (in git, etc) where Storybook lives and points to the components in the app. (The app has tons of devs in and out of it, and dropping a bunch of Storybook packages in there, as well as introducing legacy-peer-dependencies thanks to webpack 5, would be quite frowned upon).
I also want devs to have a good experience being able to use Storybook to write components, so I want Storybook to see the current code of the project components, not some exported package. And same as above, there are many devs and a lot of inertia, so moving components to a separate standalone library is not an option.
My ideal for local development:
components and stories: /MyProject-App/src/Components/...
storybook app. : /MyProject-Storybook/stories/...
(Production I'm not worried about yet)
Installing Storybook inside the app works fine (as long as you run with --legacy-peer-deps). I am using the npx storybook init script and it works fine. But if I try to run Storybook out of a separate directory and target the app directory's Components, it breaks. If I run Storybook out of the app, and point it to stories/components outside that repo (which I copied and pasted just as a debugging measure), it breaks. Going up and out of the current project root breaks.
To do this, I am trying to point stories in /MyProject-Storybook/.storybook/main.js to ../../MyProject-App/src/Components.... When I do this and npm run storybook, I get the error output:
File was processed with these loaders:
* ./node_modules/#pmmmwh/react-refresh-webpack-plugin/loader/index.js
* ./node_modules/#storybook/source-loader/dist/cjs/index.js
**You may need an additional loader to handle the result of these loaders.**
The error is always on some basic ES6 syntax, arrow functions etc. If I run the same Storybook install out of MyProject-App (same version numbers / same main.js just pointed at the local path instead of the ../other path) it works.
In addition to this, I tried it the other way - running storybook out of the App folder (where I know it runs), and only changing the main.js stories directory to an outside-that-repo folder where I copied my Components and stories into. It breaks in the same way - I get the same You may need an additional loader to handle the result of these loaders. message, with it pointing to any example of ES6 syntax as an 'error'.
I found this similar question - Storybook can't process TS files outside of the project
recommending to look into Storybook's webpack loaders - https://storybook.js.org/docs/react/builders/webpack
So I updated my .storybook/main.js to be the following:
module.exports = {
stories: [
'../../MyProject-Storybook/src/**/*.stories.mdx',
'../../MyProject-Storybook/src/**/*.stories.#(js|jsx|ts|tsx)'
],
addons: [
'#storybook/addon-links',
'#storybook/addon-essentials',
'#storybook/addon-interactions',
'#storybook/preset-create-react-app'
],
framework: '#storybook/react',
core: {
builder: '#storybook/builder-webpack5'
},
webpackFinal: async (config, { configType }) => {
config.module.rules.push({
test: /\.(js|jsx)$/,
use: [
{
loader: require.resolve('babel-loader'),
options: {
reportFiles: ['../**/src/**/*.{js,jsx}', '../../MyProject-Storybook/**.stories.{js,jsx}']
}
}
]
});
config.resolve.extensions.push('.js', 'jsx');
return config;
}
};
but to no avail - output from npm run storybook remains unchanged, an excerpt:
File was processed with these loaders:
* ./node_modules/#pmmmwh/react-refresh-webpack-plugin/loader/index.js
* ./node_modules/#storybook/source-loader/dist/cjs/index.js
You may need an additional loader to handle the result of these loaders.
| backgroundColor: { control: 'color' },
| },
> } as ComponentMeta<typeof Button>;
|

Why .js [file Extension] is not added while importing a component in reactJS?

We are creating different components in reactJS,
Example:
App.js
index.js
LandingPage.js
.....
While importing this component in another component, we are not adding the extension .js
Example:
index.js:
import App from './App'
// here './App' we are not adding .js
Does anyone know the reason why?
Your Webpack config is taking care of resolving the common extensions (ie: .js or .jsx). If your project is using create-react-app, then this is already done for you behind the scenes.
Create-react-app already resolves the following extensions automatically:
extensions: [".web.js", ".mjs", ".js", ".json", ".web.jsx", ".jsx"],
More info here
https://github.com/webpack/docs/wiki/Configuration#resolveextensions
It all done by webpack module resolution, a resolver is a library which helps in locating a module by its absolute path.
The dependency module can be from the application code or a third-party library. The resolver helps webpack find the module code that needs to be included in the bundle for every such require/import statement. webpack uses enhanced-resolve to resolve file paths while bundling modules.
Once the path is resolved based on the above rule, the resolver checks to see if the path points to a file or a directory. If the path points to a file:
If the path has a file extension, then the file is bundled straightaway.
Otherwise, the file extension is resolved using the resolve.extensions option, which tells the resolver which extensions are acceptable for resolution e.g. .js, .jsx.
Resolve extensions: These options change how modules are resolved. webpack provides reasonable defaults, but it is possible to change the resolving in detail.
In webpack.config.js
module.exports = {
//...
resolve: {
enforceExtension: false
}
};
If the value is true here, it will not allow extension-less files. So by default require('./foo') works if ./foo has a .js extension, but with this (enforceExtension) enabled only require('./foo.js') will work.
Add .js to resolve/extensions in webpack.config.js
resolve: {
extensions: [".ts", ".js", ".mjs", ".json"],
symlinks: false,
cacheWithContext: false,
},

Shared components with ejected create-react-app projects

I have several projects that were created with create-react-app and have been ejected. Now, I have some components that are duplicated in each of the projects. Instead, I would like to have one shared component in a directory above the project directories.
The directory structure would be something like this:
- shared_components
- MySharedComponent.js
- project1
- project2
- project3
I updated the webpack.config.js files in my projects to allow importing files outside the src directory by adding my shared_components directory to the ModuleScopePlugin:
{
resolve: {
plugins: [
new ModuleScopePlugin([paths.appSrc, paths.mySharedComponents], [paths.appPackageJson]),
],
}
}
This successfully allows the files to be imported, but my shared_components directory doesn't seem to get compiled by the babel-loader.
I am getting the following error:
SyntaxError: /path/to/shared_components/MySharedComponent.js: Unexpected token <
This error occurs at the start of the JSX in my component, which is presumably caused by it never getting compiled to plain Javascript.
I tried updating the babel-loader config to include my shared directory, but it is not working:
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
include: [paths.appSrc, paths.mySharedComponents],
loader: require.resolve("babel-loader"),
// ...the rest of the config is just the defaults
}
How can I get my JSX component to successfully compile?

Include only used imports in the packaged bundle ReactJS

I wanna use only one component from Material Ui library . I know i can import only one component using ES6 import but does webpack treeshake and remove other components from the library or include them in production .
Please help me.
Webpack from v2 onwards eliminates unused exports in two steps:
First, all ES6 module files are combined into a single bundle file in which exports that were not imported anywhere are not exported, anymore.
Second, the bundle is minified, while eliminating dead code. Therefore, entities that are neither exported nor used inside their modules do not appear in the minified bundle. Without the first step, dead code elimination would never remove exports.
Unused exports can only be reliably detected at build time if the module system has a static structure.
Webpack doesn't perform tree-shaking by itself. It relies on third party tools like UglifyJS to perform actual dead code elimination.
To do that, you would install it using
npm install --save-dev uglifyjs-webpack-plugin
And then adding it into the config:
webpack.config.js
const path = require('path');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new UglifyJSPlugin()
]
};
So when you add this config, your unused exports are not longer present in the minified build.
Webpack 5 comes with terser-webpack-plugin out of the box, hence you can just import it and configure as you wish.

Syntax Error In IE 11 for this node_moduels

I am getting a syntax error in IE when this component of react is loaded in the webpage. Has anybody got the same problem? This is an inherited package, and a syntax error from node_modules makes no sense?
"use strict";
/* WEBPACK VAR INJECTION */(function(module) {
const colorConvert = __webpack_require__(/*! color-convert */ "./node_modules/color-convert/index.js");
const wrapAnsi16 = (fn, offset) => function () {
const code = fn.apply(colorConvert, arguments);
return `\u001B[${code + offset}m`;
};
const wrapAnsi256 = (fn, offset) => function () {
const code = fn.apply(colorConvert, arguments);
return `\u001B[${38 + offset};5;${code}m`;
};
If you are using newer versions of Node/NPM, check your package.json file -> "browserslist" section.
This is the default "browserslist" created for you if you do not have one defined:
In this case, if you run "npm start" on your LOCAL Environment, Babel will not create Polyfills for IE11 because its not included as a target browser in "development". To get this working, I deleted my node_modules directory completely, ran 'npm install', updated package.json with:
and ran 'npm start.
The reason why this fails is that babel or your other favorite transpiler might ignore node_modules (if that's how its configured), so you need to include it manually because IE does not support arrow function syntax.
First, if you search for wrapAnsi16 or wrapAnsi256 function names online it'll point you to common npm packages, such as: ansi-styles, chalk or color-convert, debug, strip-ansi, etc.
If you are using Webpack you can add the following to your rules:
module: {
rules: [{
exclude: /node_modules\/(?!(color-convert|ansi-styles|strip-ansi|ansi-regex|debug|react-dev-utils|chalk)\/).*/
}]
}
or, easier to read:
module: {
rules: [{
include: [
path.resolve(__dirname, 'node_modules/ansi-styles'),
path.resolve(__dirname, 'node_modules/strip-ansi'),
... other's here...
path.resolve(__dirname, 'src'),
]
}]
}
Hope this helps somebody in the future ;)
TLDR; you don't need this library, just run
npm run build
And it will be excluded from your build.
I have same problem with create-react-app, and I solve it (no). From my discovery, this library should not appear in browser, because it was designed for nodejs environment. Also I found, this library come to me as dependency of jest, and jest is dependency for tests and it come as dependency for react.
So, I run
npm run build
server -s build
And try my application in IE. And it work. So, when you run
npm start
It make file including dev dependencies and other garbage that should not appear in production and in browser at all. When you run
npm run build
It make file only with required project libraries.
I had similar issue #punkbit solution and installing 'react-app-polyfill'
and importing it at the top of the index.js file solved it
import 'react-app-polyfill/ie11';
import 'react-app-polyfill/stable';
If it still does not work delete node-modules and reinstall also clear cache in IE.
All the best :)
This problem occurs because your compiled code contains (modern) ES6 syntax whilst IE11 only supports ES5.
A way to fix this is to instruct webpack to specifically compile the mentioned packages into ES5;
module: {
rules: [{
test: /\.(tsx?|js)$/,
include: [
// These dependencies have es6 syntax which ie11 doesn't like.
// Whenever you see a "SyntaxError" that crashes IE11 because of a new lib, add it here.
path.join(__dirname, 'node_modules/react-intl'),
path.join(__dirname, 'node_modules/pkce-challenge'),
path.join(__dirname, 'node_modules/fuse.js')
],
use: [{
loader: 'ts-loader', // Or whatever loader you're using
}]
}]
}
for me this was: fuse.js, pkce-challenge and react-intl.

Resources