Need Root Directories in Browserify and Using NPM (eliminating the constant use of '../../../..' in both cases)

Despite my extensive search for a solution to this issue, I have been unsuccessful so far – even after referring to the amazing gist on improving local require paths and thoroughly reading the Browserify handbook section on Avoiding ../../../../... I am struggling to find a viable solution for this problem.

I am currently working on a library developed with Browserify, which I intend to publish on npm. You can check it out yourself if you wish to test what I am describing here. However, the challenge lies in my desire to release it on NPM without relying on relative paths when calling require(), as it is done when using Browserify.

By utilizing Browserify's opts.paths, I managed to transform my require()s from conventional forms like

var Classy$Base = require('./base')
// and in another file
var Classy$Module = require('../../module')

to

var Classy$Base = require('classy/base')
// and in another file
var Classy$Module = require('classy/module')

This modification was successful and effective! When I execute gulp bundle, I receive a functional classy.bundle.js output, making everything seem right.

However, upon performing a npm link and linking it in another project (also using Browserify) via npm link classy-js, things start to fall apart. Error messages originating from require('classy-js') claim instances of "could not find module 'classy/base' from 'node_modules/classy-js/src...'" among others.

I envision creating a library where I can simply call require('classy-js'), along with

require('classy-js/classy/module')
to access all other beneficial submodules of the library whilst maintaining non-relative paths within the library's code.

Is there any feasible way to achieve this?

I experimented with app-module-path, which unfortunately results in Browserify errors, and I also tested require-root with similar outcomes.

I tried symlinks and incorporated an npm postInstall script for automatically setting up symlinks, yet nothing seemed to work.

It feels like this should be a more straightforward process...

Answer №1

After solving the problem at hand, I can't help but feel like the solution is rather simple and not very elegant. While looking into JMM's answer which may have been a viable option, I decided to take a different approach.

Both projects are using Browserify, allowing me to easily require 'classy' in the second project by simply using require('classy-js'), as it automatically looks in the node_modules directory. However, when it comes to resolving paths such as require('classy/base'), Browserify doesn't utilize the opts.paths that were used to build the Classy bundle. This results in numerous errors.

The solution I found entails an npm postinstall script that creates an empty node_modules folder (given that Classy only has devDependencies) and establishes symlinks for node_modules/classy to src/classy, and another symlink for node_modules/selfish (another top-level module in src/) to src/selfish. By implementing this method, we avoid tampering with the opts.paths of the separate project, ensuring that our improved require() statements operate seamlessly in both the browser and node.

The postinstall script configuration appears as:

// package.json
...
  "scripts": {
    "test": "gulp test",
    "postinstall": "mkdir node_modules && node create-symlinks.js"
  },
...

and the contents of create-symlinks.js are as follows:

// create-symlinks.js
var fs = require('fs')

var c  = '../src/classy'
  , s  = '../src/selfish'
  , cd = 'node_modules/classy'
  , sd = 'node_modules/selfish'
  , e  = undefined

e = fs.existsSync(cd);
if (!e) {
  console.log('link', cd, 'to', c)
  fs.symlinkSync(c, cd, 'dir')
}

e = fs.existsSync(sd)
if (!e) {
  console.log('link', sd, 'to', s)
  fs.symlinkSync(s, sd, 'dir')
}

While this method may seem somewhat unconventional, it effectively resolves the issue at hand while adopting a similar convention to the symlink suggestion proposed in the "Better Local Requires" Gist. It might not be the most graceful solution, but it gets the job done.

In terms of accessing submodules within Classy, I opted to expose any public API submodules (like Classy$Module) as a property of the main Classy object. Therefore, instead of requiring modules individually like so:

var Classy$Module = require('classy-js/module')

We can now simply do:

var Classy$Module = require('classy-js').Module

Although this method is not perfect, it serves its purpose adequately and proves to be sufficient for our needs.

Answer №2

While it may not be the most conventional method, I haven't come across a package on npm that specifically caters to this functionality. However, I believe the following approach might just do the trick:

// Declare the module name, similar to the `name` property in `package.json`.
var Classy$Base = require('classy-js/base')
// Followed by another file
var Classy$Module = require('classy-js/module')

In regards to this section:

After running npm link, followed by executing npm link classy-js in a different project (also utilizing Browserify), I encountered some issues.

To address this and align it with the initial suggestion, consider linking classy-js back to itself. For instance, if you have a directory structure like /somedir/subdir/classy-js, ensure there exists a /somedir/subdir/node_modules. Then, navigate to /somedir/subdir and run npm link classy-js. Be cautious not to have a

/somedir/subdir/classy-js/node_modules
and avoid linking from /somedir/subdir/classy-js to prevent any circular references that could disrupt module resolution.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to access the api variable in JavaScript

When attempting to retrieve variables from an API object, I encountered the obstacle of them being nested inside another object named "0" in this particular case. Here is a screenshot from the console: enter image description here Below is the JavaScrip ...

Troubleshooting JQuery Variable Overwriting Problem

Here is the code snippet I am working with: <script> $(document).ready(function() { var settings_image ={ url:"<?php echo site_url('/cms/editor/upload/images');?>", method: "POST", fileName: "file", returnType: ...

The array is not receiving the objects as intended

I'm facing an issue with my event listener that is supposed to push new messages to an array, but it seems to only be pushing the strings. Here is the code snippet: async function consume() { try { let result = []; const connection = await a ...

Error message: Component is unable to access the $store property because it is undefined

After doing extensive research and reading numerous similar questions on various platforms, I am still unable to resolve my issue. I have a component containing a login form that triggers a method to dispatch a $store action for logging in the user via fi ...

In JavaScript, the event.defaultPrevented property will never be set to true

I've been experimenting with events in my script, but I'm struggling to understand the functionality of event.preventDefault()/event.defaultPrevented: var e = new Event('test'); e.defaultPrevented; > false e.preventDefault(); e.d ...

What is the reason for the JavaScript TypeError (undefined) being triggered when this object is used within a function?

I have defined a new object like this: function node(){ this.tag = null; this.Tdata = []; this.Tchilds = []; } Now, I am trying to use this object in a function: function Validate(root /*Ass ...

The module 'measuretool-googlemaps-v3' could not be located

My project was built using 'create-react-app' and I have included an import in one of the files like this: import MeasureTool from 'measuretool-googlemaps-v3'; Everything runs smoothly when I run my project, but I encountered an issue ...

What is the best way to send information to a component using Props in Vue2?

Recently, I created a .Vue file to showcase information about a cafe on the Cafe Details Page. However, to streamline template updates, I decided to extract certain parts of this details page and turn it into its own component. This led me to create a new ...

Change the value of a single element in an array using a component in ReactJS

I'm attempting to pass an array value to a specific index in one component and then assign a desired value from the child component. I need it to work this way because I'm developing a survey app where the number of questions can vary. This is j ...

"Encountered a hiccup while trying to install bcrypt

I am having trouble with installing bcrypt through npm on my computer. I keep encountering errors and despite trying to troubleshoot, I have not been successful in resolving the issue. Can someone provide guidance on how to diagnose and fix this problem ...

Issue with Ag-Grid's getRowClass not locating the appropriate CSS styling

I am facing a simple challenge at the moment. My goal is to dynamically change the background color of my rows, with the intention of incorporating this feature when expanding or contracting groups. Currently, I am attempting to utilize gridOptions.getRow ...

Executing several asynchronous functions in Angular 2

I am currently developing a mobile app and focusing on authentication. In order to display data to the user on my home page, I need to connect to various endpoints on an API that I have created. Although all endpoints return the correct data when tested i ...

What is the best way to transform HeadersInit into an Object<string,string> data type?

In short, I am faced with the task of converting the headers of a RequestInit into a format that another library can comprehend. This particular library requires the headers to be in the format of Object<string, string>. Initially, I attempted someth ...

Stop the scrolling behavior from passing from one element to the window

I am facing an issue with a modal box window that contains an iframe. Inside the iframe, there is a scrollable div element. Whenever I try to scroll the inner div of the iframe and it reaches either the top or bottom limit, the browser window itself start ...

What is the process for including an SVG file in my JavaScript .textContent?

I've been struggling to add an exclamation SVG to this section, but for some reason I can't make it work. I've searched on Google for a solution, but haven't found one yet. The SVG file is already downloaded and stored in my project fo ...

Modify Ripple Color on Material UI < Button /> Click Event

This is my custom button component called <MyButton /> import React from 'react'; import { withStyles } from '@material-ui/core/styles'; import Button from '@material-ui/core/Button'; const styles = theme => ({ bu ...

Possible Inconsistencies with the LookAt Feature in Three.js

Attempting to use the lookAt function to make zombies move towards the character has been a challenge. The problem lies in the fact that they are not turning correctly but at odd angles. Here is the code snippet I tried: var pos = new THREE.Vector3(self ...

The functionality of Jquery .slideToggle("slow") seems to be glitchy when used as a table expander

I attempted to implement the .slideToggle("slow"); feature to my table, following the instructions detailed here: W3Schools The toggle effect seems to be functioning, but not as expected. I want the effect to behave similar to the example on the W3School ...

Is it appropriate to include a function within a loop?

I'm curious to know if it's considered good practice to call a function inside a loop. Both of the following code snippets produce the same result, but I want to add clarity by using a function. Is this considered good practice? Thank you. Code ...

Working with conditional statements in ReactJS and Javascript

As I navigate the circle object using arrow keys, I am facing a challenge in limiting its movement within the height and width of the svg area. Despite my efforts to use conditional statements, the ball tends to get trapped at the edges and fails to contin ...