I wrote a very simple local module to manage a few lines of localized text.
It uses node's require to load the language files, but I'm having trouble with paths, most likely.
I'm getting the Cannot find module error.
File structure
.
+-- local_modules
| +-- lang
| | +-- package.json
| | +-- index.js
+-- locale
| +-- en.js
| +-- de.coffee
+-- init.js
+-- index.coffee
+-- package.json
Relevant module code
Should require the file if it is not already loaded.
join = require('path').join;
_config.path = './locale';
lang = 'en';
_locales = {};
if(!_locales[lang]){
_locales[lang] = require(join(_config.path, lang));
}
Every file in the locale directory is a typical Node.js module, for example en.js:
module.exports = {
test: 'Hello World!'
};
The local module exports a function(req, res, next){}, which is used as Express middleware and is supposed
to attach the required object with localized strings onto res.locals, however, I'm seeing Cannot find module 'locale/en' error.
I've tried to manually add the .js extensions (but that shouldn't be neccessary as far as I know).
I have also tried different variations on the path, such as locale or /locale.
The module is called in index.coffee.
App is launched using init.js, which contains the following:
require('coffee-script/register');
require('./index');
Maybe it's just that the module is a .js (and the module itself doesn't have CoffeeScript as a dependency) so it can not load a .coffee file? Although CoffeeScript should be registered globally, or am I wrong? Either way, it doesn't work with the .js file either, so I guess it has something to do with paths.
path.join() also normalizes the created path, which (probably) means the ./ part was always removed, and what remained was a relative path.
Instead, when path.resolve() is used, it creates an absolute path, which is what is needed in this case.
Related
I have used TypeScript to create a jQuery plugin. Currently, I have a nodejs app as the host of my typescript files during development. I would edit my *.ts files in VS Code and use tsc --build to compile them and could debug inside VS Code (with additional *.html files referencing the generated .js files).
The folder structure was quite simple.
+-- client
| +-- ClientApp.ts
| +-- DynamicApp.ts
| +-- Interfaces.d.ts
| +-- ThirdParty.d.ts
| +-- tsconfig.json
+-- tsconfig.json
+-- tsconfig-base.json
ClientApp.js - This file was distributed to clients that wanted to use our plugin and had minimal code that was actually a 'shim' for our addin. This code is/was rarely touched because we didn't want to go through the hassle of having clients update their local .js file.
DynamicApp.js - This file is the actual implementation of our addin and changes frequently. We host this in a Content Management System (CMS) that serves the file to the client. This is possible via ClientApp.js calling $.ajax() to our CMS to get the file content, then it injects it into the DOM.
const script = document.createElement('script');
script.innerHTML = contentFromCMS;
body.appendChild(script);
This allowed us to make updates to the actual implementation of the plugin and test/deploy at our speed to the production CMS.
Below is what I had for 'tsconfig.json' settings, which I think I basically got when I followed a tutorial to create this site a long time ago. To be honest, I'm not up to complete speed on all the settings/power of tsconfig.json - especially now, 2-3 years later.
Contents of tsconfig-base.json (root)
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"declaration": true,
"sourceMap": true,
"outDir": "./build",
"removeComments": false,
"strict": true,
"esModuleInterop": false,
"forceConsistentCasingInFileNames": true,
"listEmittedFiles": true
}
}
Contents of tsconfig.json (root)
{
"extends": "./tsconfig-base.json",
"references": [
{ "path": "./server" },
{ "path": "./client" }
],
"files": [
/* Empty files array specifies that no files should be compiled directly as part of this master package */
]
}
Contents of client/tsconfig.json
{
"extends": "./../tsconfig-base.json",
"compilerOptions": {
"composite": true,
"outDir": "./../public/KatApp/Global",
"tsBuildInfoFile": "./../build/cache/client/.tsbuildinfo",
"suppressImplicitAnyIndexErrors": true
}
}
My Refactor Problem
I have made a .NET Core site as the host (since neither the nodejs site nor .NET Core site are the actual host of the files during live execution, I was just more comfortable with .NET Core and Visual Studio Proper). I basically want to break apart ClientApp.ts and DynamicApp.ts into separate files for each class, but I have to keep the output of simply ClientApp.js and DynamicApp.js. Currently, the DynamicApp.ts is more than 7K lines and it is getting unwieldly to navigate, especially for developers who aren't in there frequently.
As I understand, to accomplish this I have to use the "outFile": "" setting in tsconfig.json. Additionally, it seems you can only have one outFile per tsconfig.json file and only one tsconfig.json per folder, so I restructured my application to look like this.
+-- Scripts
| +-- ClientApp
| | +-- ClientApp.ts
| | +-- ClientHelper.ts
| | +-- tsconfig.json
| +-- DynamicApp
| | +-- DynamicApp.ts
| | +-- DynamicHelper.ts
| | +-- tsconfig.json
| +-- Shared
| | +-- Interfaces.d.ts
| | +-- ThirdParty.d.ts
| +-- tsconfig.json
So the goal is to combine all files in the ClientApp folder into ClientApp.js and all the files in DynamicApp folder into DynamicApp.js.
Originally, since all the *.ts files were in same folder, everything just worked. I didn't have any /// <reference path="" /> declarations or anything. Now, with this setup and things in separate folders, I'm encountering some frustrating issues along with issues that prevent it from building.
Code Duplication - Remember that ClientApp will dynamically inject the code from DynamicApp into the DOM, so I can't have duplicated classes, enums, etc. generated in both ClientApp and DynamicApp otherwise I would assume it would cause compile errors and run time.
Enums - ClientApp.ts has an enum declared that is used in ClientApp.ts, DynamicApp.ts, and Interfaces.d.ts. I tried using reference, "files" setting in tsconfig.json, changing to declare enum inside my Interfaces.d.ts file, but all were preventing the build from working for different reasons or causing runtime exceptions. So not only do I have a problem getting the enum shared across all files, but the I haven't been able to find any direction on how reference an enum from a *.d.ts file in general.
Dependencies - Currently, ClientApp has some static methods that are also called by DynamicApp. But in the new folder structure, if I add a reference inside DynamicApp to ClientApp, when DynamicApp compiles, it regenerates/injects all the code from ClientApp again which would cause js errors I assume. My game plan to get around this was to have all the shared code assigned on various $.fn.ClientApp.methodABC=function(){...} items in a shared *.ts file, and reference that from both ClientApp and DynamicApp. Then, even with code generated twice and ran, yes it was wasted overhead/re-assignment, but at least I don't think it would cause client side compile errors.
I feel like there is something easy I am missing (and unfortunately, I'm not up to speed on module loaders/resolvers on the client side and not sure if they'd even work in our scenario).
I want to use my .env variable presend in my nodejs root folder in reactjs. I tried using process.env.TEST but i always get undefined. any solutions?
My folder structure.
Project root
|-client
| |- //react project files
| |-app.js
|
|- //nodejs project files
|-.env
|-server.js
I want to access my .env variables in app.js and its components
You can use find-up to get your variables in your whole monorepo.
Find here a bright article on the usage.
I am trying to find the location of the source file for an internal module called by process.binding('base_filter') in "base-filter.js".
It's a react/electron app using electron-prebuilt.
This script is located in:
+-- electron-prebuilt
| +-- dist
| +-- resources
| +-- electron.asar
| +-- filtering
| +-- api
| +-- exports
| +-- base-filter.js
I've searched exhaustively for solutions, I've tried:
var natives = process.binding('natives');
for (var key in natives) {
console.log(key);
}
From How to obtain a list of all available Node.js modules?
Which didn't show the module.
I've tried:
node.js Internals: How can I find out where `process.binding('eval')` gets defined?
What is `process.binding('fs')` in `fs.js`?
I've tried batch searching every single file in the code-base for mention of "base_filter" with no success, i also tried searching my PCs appdata and user files thinking it might be caching somewhere, no success.
I'm wringing my hair out over this, I just need to be able to trace where it's being loaded from so i can edit it/ fix any problems.
I would appreciate any help, thank you.
I've started to play around with using NPM Scripts and BabelJS to transpile my ES2015 AngularJS project. The problem is that the concatenated order is not correct and causes nomod errors.
Given this directory structure:
MyApp
+- src
| +- dashboard
| | +- search-bar
| | | +- search-bar.directive.js
| | | +- search-bar.service.js
| | | +- search-bar.spec.js
| | +- dashboard.module.js
+- dist
| +- js
| | +- dashboard.js
Ideally, dashboard.module.js should be the first file because that is where the actual dashboard module is created, followed by everything in /search-bar which actually doesn't require any order at all. The search bar is a feature/component, not a new module and is all part of dashboard.
The problem seems to be that simply running BabelJS will just concatenate all the files together using the same structure as the filesystem does.
babel ./src/dashboard/**/*.js -o ./dist/js/dashboard.js
There are also weird things when messing with the wildcards to try make sure all files are captured.
How can I process dashboard.js first before any of the other components?
It turns out you can specify many globs as input files.
Try using this command:
babel ./src/dashboard/*.js ./src/dashboard/**/ -o ./dist/js/dashboard.js
This will first process any .js immediately inside of /dashboard followed by the rest of the directory.
Gotcha: This will only really work as long as you only have the one file inside of the /dashboard root. If you were to add dashboard.config.js or any other file, then this would process those files in that filesystem order. Unfortunately, dashboard.config.js comes before dashboard.js so your problem will continue. :(
Also, if you have other files in /dashboard root or you have other kinds of .js that you don't want to be included, you'll need to ignore them.
Try:
babel ./src/dashboard/**/*.js ./src/dashboard/**/ --ignore *.spec.js --ignore *.conf.js -o ./dist/js/dashboard.js
This will put things in the right order and also skip any karma.config.js or search-bar.service.spec.js files you may put in there. I assume that you don't want those actually being used in production.
I am building a Node app that returns results for a search using a Google Custom Search Engine(CSE).
I am going to separate the part of the app that sends the request to Google and returns the results into a module.
I use dotenv already in the app to store MongoDB credentials and the app's URL.
I also want to use dotenv in the module to store the Google CSE ID and the API key for the CSE.
I want my module to work independently of the main app but also to use the main app's dotenv file when it's a module.
Currently my module structure looks like this:
module
|
+-- node_modules
| |
| \-- dotenv
| |
| \-- (dotenv module's files....)
|
+-- .env
|
\-- index.js
This works perfectly on its own. The .env file stores the required environment variables and I can access them in the index.js file by requiring the dotenv module.
When included in the main app the structure looks like this:
app
|
+-- node_modules
| |
| +-- dotenv
| | |
| | \-- (dotenv module's files....)
| |
| \-- my_google_search_module
| |
| +-- node_modules
| | |
| | +-- dotenv
| | |
| | \-- (dotenv module's files...)
| |
| \-- index.js
|
+-- .env
|
\-- index.js
This also works. I store all the environment variables in the main app's .env file and by requiring dotenv in the app's index.js I can access those variables. Plus, the "my_google_search_module" seems to be pulling its required variables from the .env file in the root of the app. There is no .env file in the module.
My question is am I doing this the right way?
I have researched this further and can confirm that the module's .env is pulling the required environment variables from the app's .env file.
I believe this section from the dotenv readme, though not exactly related, verifies that -
https://www.npmjs.com/package/dotenv#what-happens-to-environment-variables-that-were-already-set
We will never modify any environment variables that have already been
set. In particular, if there is a variable in your .env file which
collides with one that already exists in your environment, then that
variable will be skipped. This behavior allows you to override all
.env configurations with a machine-specific environment, although it
is not recommended.
Yes, you are doing in a right way. There must be a single .env file in a whole project. But there is a trick to include it in the different directory structure.
For example:
Your index.js file is in /app/src, your .env file is in /app. Your index.js file has this
dotenv.config({path: "../.env"});
You could also use dotenv.config({path: path.join(__dirname, "../.env")});
for node projects, i would suggest to use npm package dotenv. You can find details on how to use it. do not forget to include require('dotenv').config() at the start of your project file, say index.js.
Now you can use .env contents anywhere you need. For example i want my server port to be 4000 which i define in .env as PORT=4000. Now, to use .env variables anywhere, simply provide variable name in suffix such as process.env.PORT. That is it. Though i am late on this post, hope this could be of any help.