Make webpack ignore a certain import - javascript

I'm trying to create a desktop app using ElectronJS and ReactJS.
The renderer process is bundled using webpack, since i'm using JSX in it.
When I try to import anything from electron (e.g. import electron from 'electron';, or const electron = require('electron');) in the renderer process I get these 2 errors when I either try to build it with webpack (the web part), or when I use webpack-dev-server and open the localhost URL in electron:
https://pastebin.com/WdkCcPzm
Note that I'm not using create-react-app, that bundle.js is webpack's output, App.jsx is the file I'm trying to import electron from, that I want to import electron to access the ipcRenderer variable and that I'm not attempting to import fs from the renderer process (or from the main process for that matter).
A solution I found was to bypass webpack's packing by adding this line to my index.js
eval('window.Electron = require("electron")');
and accessing electron though the variable Electron (the capital E is because vs code recognizes that as a namespace even though electron isn't imported, and thus I still get code completion)
But that's really ugly and I was hoping there was another solution.

To build bundles for the renderer process of Electron apps, webpack provides a special target parameter.
Add this to your webpack config:
target: 'electron-renderer'
See documentation: https://webpack.js.org/configuration/target/

Related

Cannot import Node, JS, or Electron library in Angular Typescript module no matter what I try

I'm fairly new to stack overflow, so if I don't ask the question correctly feel free to help me out.
I've scoured every stack overflow and google article I can find and nothing works to import Electron, any other Node modules, or any native JS modules--I can only import and use Angular/typescript modules. I'm trying to import electron and use it in an angular app. I am also trying to use __dirname. For electron I've tried:
const { remote } = require('electron');
const { remote } = (<any>window)require('electron');
import { ipcRenderer, BrowserWindow, electron } from 'electron';
import * as remote from '#electron/remote'
For __dirname I've tried:
import * as fs from 'fs';
import { readFileSync } from 'fs';
import readFileSync from 'fs';
and for the implementation:
import.meta.url
process.cwd()
__dirname //worth a shot I guess
I've combined these options, and nothing works. I've run npm install --save-dev #types/node, and when that didn't work tried deleting the node_modules folder and ran npm install. "types": ["node"] has already been added to tsconfig.json's compilerOptions.
Here is one of my errors:
Error: src/app/electron/electron.service.ts:3:20 - error TS2591: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i --save-dev #types/node` and then add `node` to the types field in your tsconfig.
3 const { remote } = require('electron');
~~~~~~~
I've already installed #types/node. It also almost always posts the following error. I have no clue what it's for, as it shows even when I'm not importing 'fs'.
Error: ./node_modules/electron/index.js
Module not found: Error: Can't resolve 'fs' in '/Users/user/Programming/Git/project/node_modules/electron'
resolve 'fs' in '/Users/user/Programming/Git/project/node_modules/electron'
Parsed request is a module
using description file: /Users/user/Programming/Git/project/node_modules/electron/package.json (relative path: .)
Field 'browser' doesn't contain a valid alias configuration
resolve as module
looking for modules in /Users/user/Programming/Git/project
using description file: /Users/user/Programming/Git/project/package.json (relative path: .)
Your browser cannot run modules written in C++ like fs and electron. Node.js can do it because node developers specifically created node to be able to load binary modules (written in C++). Browsers can only run javascript modules.
As such builders such as Webpack ignore these modules simply because it does not make sense to include them.
You cannot use fs and electron in your Angular app. You can however use Angular in your electron app (because electron was created to run javascript code and Angular compiles to pure javascript code).
Trying to use fs or electron in Angular is a little bit like trying to import Internet Explorer or Adobe Photoshop in Angular.

How to distribute package for expo? (.web.js, .js configuration)

I want to distribute a package for expo. This package was created while building my app in expo SDK36.
Like many expo dependencies, I use massively the .ios.js, .android.js and .web.js extensions.
While importing a source I have distributed on npm, resolver only import .js without any distinction.
As an example this package should work with expo:
This is the #expo/webpack-config resolved extensions:
[
".web.expo.ts",
".web.expo.tsx",
".web.expo.mjs",
".web.expo.js",
".web.expo.jsx",
".expo.ts",
".expo.tsx",
".expo.mjs",
".expo.js",
".expo.jsx",
".web.ts",
".web.tsx",
".web.mjs",
".web.js",
".web.jsx",
".ts",
".tsx",
".mjs",
".js",
".jsx",
".json",
".wasm"
]
But it does not, I have to manually import by suffixing in my sources with.web.
How can I configure expo or my distributed package in order to be able to import proper sources for each environment when sources are imported from node_modules ?
Edit
I was wrong to expect my extensions to work with the main field of my package.json, I have reconfigured my repo with :
/home/dka/workspace/github.com/yeutech-lab/react-cookiebot/src
├── CookieBot.js
├── CookieBot.native.js
└── index.js
Questions :
I have used .native.js so my reactjs users (not only expo and react-native users) will import the .js file by default
Because of (1), others react user's (neither react-native nor expo) don't need some sort of extra configuration to support react-native extensions .web.js, .ios.js, .android.is, .native.js and .js.
In case I do prefer .web.js instead of (1), it will not be possible for my react user to do as in (2), and in this case: what would be the way for them to configure react-native extensions in their project?
For all react-native users, may I know where the extension can be configured in native projects? (I believe web project can be configured in webpack with config.resolve.extensions)
Regarding the main field
In a node module, you can make the bundler resolve a platform specific "main" file by deleting the file extension in your package.json.
- "main": "index.js"
+ "main": "index"
I would advise against this though as the bundler resolution could work differently in bundlers other than Webpack and Metro. It would be safer to have one "main" file re-export the contents of other platform specific modules (It appears this is what you did in your edit, but I'll leave the explanation here for completeness):
index.js
export * from './module';
module.js Vanilla JS
module.web.js React Native for web
module.native.js React Native
In case I do prefer .web.js instead of (1), it will not be possible for my react user to do as in (2), and in this case: what would be the way for them to configure react-native extensions in their project?
It's important to remember that .web.js can still be resolved even if the project isn't a React Native web project. Create React App resolves .web.js extensions for every project.
On web, users can configure their platform extensions by modifying the config.resolve.extensions field of the Webpack config. In Expo this can be done by running expo customize:web.
Configure native extensions
This can be done by editing the project's Metro config: Example.

Webpack - Alias folder for use within installed package

I have some reusable React components published to NPM, that I am installing and using within my React application. Is it possible for me to set an alias in my React app, that can be used within these NPM components? For example, I want to allow the use of a folder common, which is within my React App, within the React components. So if I do this in my React components, it should work
import someVal from 'common';
I am bundling these React components with Webpack, and sending down the transpiled, bundled version for use within the React application. I tried setting the alias the regular way within the React app webpack config (by setting resolve.alias), but it does not work. Can this be done? Or am I approaching this incorrectly? Any suggestions would be great, thanks!
Edit: So the React components from NPM are within my node_modules folder, and it is already bundled up via it's own Webpack config. I then run these components through my React application Webpack config as well (I'm whitelisting the folder), in the hopes that the new common alias will be added there. But no luck. I keep getting a
someVal is undefined error.
My common file has the following: Ignore the logic for now (I'm only posting a part of the code)
import _myClass from '../components/MyClass';
const myClass = _myClass; // Other things are done to it
export default myClass;
In my React components Webpack bundle file (after I fixed the default import statement)
/* harmony import */ var common__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! common */ "./src/common/index.js");
...
return common__WEBPACK_IMPORTED_MODULE_25__["default"].myFunction({
...
});
This still seems to be looking for common within the React components package, and not within the React app package that I am trying to use this in.

webpack json-loader fails in lernajs controlled dependencies

I'm using lernajs to manage a monorepo. There, I have two packages:
app (via create-react-app)
lib (a react component transpiled with babel-cli)
When adding require('./package.json') to app, webpack compiles as expected. The json file is loaded as expected. However, when I put require('./package.json') into the lib package, webpack fails with Module not found: 'json'. The json loader is working fine for dependencies not controlled by lernajs.
The issue persists if lib is requiring another library (e.g. cheerio) that imports a json file. Same as above, if cheerio is included in app instead, it works fine.
If you don't know lernajs, it's a tool to manage monorepos and it's basically symlinking the lib package into ./app/node_modules/.
The issue was resolved by adding json-loader to the project's root directory package.json!

Browserify including entire module when only some parts used (react-addons)

I'm using Browserify to bundle serverside react.js code for the client.
However, I have a bad feeling that using a module from within an npm package results in that entire package being bundled by Browserify.
Q: Does require('react-addons').LinkedStateMixin result in the entire react-addons package being bundled into my Browserified JS?
IE: does Browserify treat require('react-addons').LinkedStateMixin the same as require('react-addons')?
If so, is there any way around this? External tools, Browserify options etc.
Browserify does not have the ability to extract parts of the functionality from a module.
What you can do though, is require the desired module from within react-addons like this:
require('react-addons/lib/LinkedStateMixin')
This will only include the one module (and it's dependencies) in your bundle. However, you now depend on the internal structure of the module. If the LinkedStateMixin is renamed, you will have to change your require statement.
#mantoni was helpful but as this is a react-addons specific question i will post my answer.
Don't use react-addons and react side by side. Instead, when requiring React use require('react/addons'). This calls a script at /addons/ that returns the full React with addons.
So for my example:
var React = require('react/addons');
var LinkedStateMixin = React.LinkedStateMixin;
//this works as normal!
React.createClass({});
Thanks guys!
In ReactJS 0.13.3 if you want to use e.g. CSSTransitionGroup you have to do the next:
var React = require('react/addons'),
CSSTransitionGroup = React.addons.CSSTransitionGroup;
And all that has to be installed – npm install react.

Categories

Resources