Webpack - How to alias dynamically according to file location? - javascript

I have a project tree where many subparts that are similar. It looks like this:
root
|-- editor
|- components
|- services
|- utils
|-- dashboard
|- components
|- services
|- utils
I want to alias 'components' (for example), to match editor/components when the requiring file is inside editor, and dashboard/components when the requiring file is inside dashboard.
Is there a way to do it (resolve dynamically)? Or do I have to assign separate aliases?

Related

How to avoid having injected CSS styles discarded by tree shaking?

I am using Rollup to bundle a React component. This component is later used in a React application bundled with Webpack. The component uses styles defined in two CSS modules -- one containing global styles and one with specific styles for the component itself.
To bundle the CSS modules I use rollup-plugin-postcss with default options. This means the CSS modules are converted into JS files, which are later injected into the document using style-inject.
To provide a more clear picture this is how my project looks like:
|- examples/example // this is the example App
|- packages/test-css // this is the component
| |- src
| | |- index.module.css // global styles
| | |- index.ts // this file imports index.module.css
| | |- myComponent.module.css // component-related styles
| | |- myComponent.tsx // this file imports myComponent.module.css
The Rollup bundle does contain the code related to style injection both for the global and component-related styles. But,the Webpack bundle for the application only contains the component-related styles (the contents of myComponent.module.css are present, but not the ones from index.module.css).
I have tried excluding *.css.mjs files (the ones generated by Rollup) from being tree-shaken, but I still have the same issue. Since the React application directly imports MyComponent it seems Webpack bypasses index.ts (where the global styles are imported) altogether.
Is there a way to instruct Webpack not to discard the CSS modules imported in index.ts without completely disabling tree shaking? (if tree shaking is disabled all the styles are loaded).
I am including a repository to reproduce the example: https://github.com/xorxsan/test-css.

ServiceWorker in React and Typescript

When creating javascript-based React projects, installing a Service Worker is just a matter of changing serviceWorker.unregister() to serviceWorker.register() on index.jsx.
With such project structure:
- src
|- index.jsx
|- serviceWorker.js
When this code gets built, the /build folder will look as followed:
- build
|- static
| |- css
| |- js
| |- media
|
|- index.html
|- service-worker.js
This will work fine and will result in the Service Worker being registered properly.
On the other hand, when setting up a project in Typescript, given the same project structure (where the js / jsx files are ts / tsx instead), the /build will look something similar:
- build
|- static
| |- js
| |- bundled-js.chunk.js
| |- bundled-js2.chunk.js
| |- ..
|
|- index.html
So it seems Typescript builds the serviceWorker bundling it with all the other js files.
This will then result in the Service Worker not being registered, with the following error in console:
Error during service worker registration: DOMException: Failed to register a ServiceWorker for scope ('https://example.com/') with script ('https://example.com/service-worker.js'): The script has an unsupported MIME type ('text/html').
The live site with the error can be seen here; The open source code can be found here.
Any idea of what I may be doing wrong?
Any tip is greatly appreciated, thank you in advance!
Ok, looking at your code your using Create React App,. This uses webpack, and it's that what is bundling, it's nothing to do with Typescript, the same would happen for Javascript when it gets bundled.
The problem is overriding the webpack config's is not easy, there is CRACO -> https://github.com/gsoft-inc/craco/blob/master/packages/craco/README.md#webpack-api
But even then it's a little tricky!! You need to tell webpack not to bundle service-worker.js, Also I would take the register bit out of the server-worker, as that can be bundled and wants to be included in your bundle.
The simplest option might be just to compile the webworker separately with Typescript directly. And again, keep the register bit separate inside your normal build.

Testing angular components outside of main project folder: module not found raw-loader

So I want to run ng test and include tests in a folder next to the projectfolder.
mainproject/
|-- src/
| |-- app/
| | |-- home/
| | | |-- home.component.spec.ts
| | |-- app-main.component.spec.ts
| |-- test.ts
| |-- tsconfig.spec.json
|-- node_modules/
|-- angular.json
|-- package.json
|-- tsconfig.json
components/
|-- common/
|-- control-bar/
|-- control-bar.component.ts
|-- control-bar.component.spec.ts
When I run ng test without including the other tests in the components folder it works as intended, but when I try to include the other components ng test fails with the following error.
ERROR in ../components/common/control-bar/control-bar.component.ts
Module not found: Error: Can't resolve 'raw-loader' in 'absolutepath\repos\components\common\control-bar'
resolve 'raw-loader' in 'absolutepath\repos\components\common\control-bar'
Parsed request is a module
No description file found
resolve as module
absolutepath\repos\components\common\control-bar\node_modules doesn't exist or is not a directory
absolutepath\repos\components\common\node_modules doesn't exist or is not a directory
absolutepath\repos\components\node_modules doesn't exist or is not a directory
absolutepath\repos\node_modules doesn't exist or is not a directory
absolutepath\node_modules doesn't exist or is not a directory
C:\Users\user\Desktop\node_modules doesn't exist or is not a directory
C:\Users\user\node_modules doesn't exist or is not a directory
C:\Users\node_modules doesn't exist or is not a directory
C:\node_modules doesn't exist or is not a directory
looking for modules in absolutepath\repos\mainproject\node_modules\#angular-devkit\build-angular\node_modules
using description file: absolutepath\repos\mainproject\node_modules\#angular-devkit\build-angular\package.json (relative path: ./node_modules)
using description file: C:\Users\user\Desktop\folder absolutepath\repos\mainproject\node_modules\#angular-devkit\build-angular\package.json (relative path: ./node_modules/raw-loader)
no extension
absolutepath\repos\mainproject\node_modules\#angular-devkit\build-angular\node_modules\raw-loader doesn't exist
.js
absolutepath\repos\mainproject\node_modules\#angular-devkit\build-angular\node_modules\raw-loader.js doesn't exist
.json
absolutepath\repos\mainproject\node_modules\#angular-devkit\build-angular\node_modules\raw-loader.json doesn't exist
as directory
absolutepath\repos\mainproject\node_modules\#angular-devkit\build-angular\node_modules\raw-loader doesn't exist
[C:\Users\user\Desktop\folder\repos\components\common\control-bar\package.json]
[C:\Users\user\Desktop\folder\repos\components\common\control-bar\node_modules]
[C:\Users\user\Desktop\folder\repos\components\common\node_modules]
[C:\Users\user\Desktop\folder\repos\components\node_modules]
[C:\Users\user\Desktop\folder\repos\node_modules]
[C:\Users\user\Desktop\folder\node_modules]
[C:\Users\user\Desktop\node_modules]
[C:\Users\user\node_modules]
[C:\Users\node_modules]
[C:\node_modules]
[C:\Users\user\Desktop\folder\repos\mainproject\node_modules\#angular-devkit\build-angular\node_modules\raw-loader]
[C:\Users\user\Desktop\folder\repos\mainproject\node_modules\#angular-devkit\build-angular\node_modules\raw-loader.js]
[C:\Users\user\Desktop\folder\repos\mainproject\node_modules\#angular-devkit\build-angular\node_modules\raw-loader.json]
# ../components/common/control-bar/control-bar.component.ts 13:34-85
# ../components/common/control-bar/control-bar.component.spec.ts
# ./src/test.ts
So raw-loader seems to be missing or it can't find it. To be clear there is only 1 node_modules in this setup and it's inside the mainproject folder.
I'm having the exact same issue and I've abandoned the search for a proper solution. For now I'm making it work by making sure the dependencies of the library are installed separately (so having a second node_modules folder in the library).
Since there is nothing to be found on the subject and the official angular documentation for creating libraries mentions that it is required for libraries to be built:
Build the library. You cannot use a library before it is built.
I'm assuming dynamically linking to unbuilt libraries without its own node_modules is simply unsupported (even though it works fine as long as there are no component classes imported in the library).

Extjs can't find resource

I deployed this project on Tomcat but when I tried to access from the webpage, the resources for ...ext-all.css and ...ext-debug.js could not be found. From eclipse, the project directory seems correct. Why can't these files be found?
Project structure
Error
I would need to see the tomcat directory structure to be sure that this is the problem, but that index.html page is looking for a webapp in your tomcat webapp directory named: ext-4.2.1.833
In other words, it is expecting something like this:
+ tomcat
|-- bin
|-- conf
|-- lib
|-- logs
|-+ webapps
|- ext-4.2.1.833
|- HelloWorldApp (or whatever you called your new app)
|- manager
|- ROOT
Is that how you have it set-up?

How to require deep nested NodeJS modules?

I have the following application structure:
application
|- config
|----- config.js
|- routes
|------ api
|-----------router.js
|- Application.js
|- package.json
In /routes/api/router.js module I need to require /config/config.js file and do the following:
require('../../config/config.js');
I found the code above ugly and want to make it more pretty. Also if I move /routes/api/router.js to another folder I have to refactor all requires. What is the best practices to require that modules and is it possible to require config.js from application folder root, something like the following:
require('/config/config.js');
Thanks.
There are a few ways to get around this problem. One is to put all your shared code (like config.js) in a directory under node_modules (using lib here in case you want to have directories other than config in there):
application
|- node_modules
|----- lib
|---------- config
|-------------- config.js
|- routes
|------ api
|-----------router.js
|- Application.js
|- package.json
So then you could require config.js using require( 'lib/config/config.js' ).
Alternatively, you could create a lib symlink in node_modules and link it to lib in your application directory structure:
application
|- node_modules
|----- lib -> ../../lib
|- lib
|------ config
|---------- config.js
|- routes
|------ api
|-----------router.js
|- Application.js
|- package.json
One other alternative, which unfortunately is discouraged by the node docs, is to use NODE_PATH which lets you specify directories that node's require() algorithm should look into. Following the same pattern as above with lib, you would do:
application
|- lib
|------ config
|---------- config.js
|- routes
|------ api
|-----------router.js
|- Application.js
|- package.json
and set NODE_PATH equal to $path_to_application/lib.
UPDATE
Found this great discussion on the topic which includes the options above as well as a few other ones.
The easiest solution is to use path.resolve. If you only give relative paths to path.resolve then it assumes they are relative to the current working directory, i.e. the project root. So all you need is:
const path = require('path');
path.resolve('config/config.js');
require('/config/config.js');
will not work as you are using the root of the system(os) not the root of the application.
var path=require('path');
var root=path.dirname(process.mainModule.filename);
or
var root=process.cwd();
will give you the root of the application. To navigate to config.js
path.resolve(root,'config/config.js)

Categories

Resources