Browserify: How would you read the contents of a directory - javascript

In my current Browserify project, I need the ability to loop through the folders of a specific directory and get a json file from each. So I'll need some kind of fs module.
Are there any specific modules you can recommend that play nice with Browserify & will let me use readdirsync / readdir or another method to read the contents of another directory?
Apparently I can't use the normal nodejs fs module, and I've looked at brfs but that only gives me access to readFile.
I would love to do something like :
// app.js
getFiles = require('./getFiles.js')():
and
// getFiles.js
module.exports = function(){
var fs = require('some_module_system');
var folders = fs.readdir('../path/to/dir', function(err, contents){
console.log(contents);
});
}
and wrap it all up with
browserify app.js > build.js

You can do this with the brfs browserify transform. It has readdir and readdirSync (and all the other fs stuff too).
First install brfs:
npm install --save brfs
then replace your 'some_module_system' with the normal 'fs' module (brfs transform will process that out when you call browserify).
After that:
browserify -t brfs app.js > build.js
and you're good to go.

Related

Get installed package root path from within package

I am building an npm package which is basically an CLI tool.
It is intended to be installed globally and used as CLI with dist/clj.js, but can also be installed as a regular dependency and accessed via dist/index.js.
From inside .js files of my package (like dist/cli.js or dist/index.js) I want to get an absolute path to the root of my package (where package.json is located).
I know this can be done with __dirname but for different files in my project it require different actions:
// dist/cli.js
console.log(require('path').join(__dirname, '..'));
// dist/a/b/c/foo.js
console.log(require('path').join(__dirname, '..', '..', '..', '..'));
Is there a better way to get the root of both globally or locally installed package from any .js file inside this package regardless of the folder this package is used in?
This code seems to work from any file within package:
const path = require('path');
let packageRootPath = path.join(path.dirname(require.main.filename), '..');
.. in the end needed to jump from src/dist to the root since all my js files are located in src/dist forders.

Set 'fs' to empty or false does not help browser-pack inside browserify to run on the web

Do you guys know why this package browser-pack was designed to work with browserify but its index.js uses fs and path?
I have the same question for browserify itself as well after I found browserify does use fs in its index.js file.
var fs = require('fs');
var path = require('path');
var combineSourceMap = require('combine-source-map');
var defaultPreludePath = path.join(__dirname, '_prelude.js');
var defaultPrelude = fs.readFileSync(defaultPreludePath, 'utf8');
I do not use CLI to run those, I run browserify through its API support like below when clicking a button on the Web UI:
import browserify from 'browserify';
const rs = browserify(fileContentStreams, opts)
.transform('brfs')
.transform(sassify, {
base64Encode: false,
sourceMap: false
}) ...
...
Since browserify already stated that:
Browserify is an open-source JavaScript tool that allows developers to write Node. js-style modules that compile for use in the browser. Browserify lets you use require in the browser, the same way you'd use it in Node. It's not just syntactic sugar for loading scripts on the client.
I cannot use Browserify on the browser side, and I did try as following in webpack.config.js but it throws errors anyway:
node: { fs: 'empty' }
or
node: { fs: false }
The former option throws fs.readFileSync is not a function while a long chain of errors were thrown for the latter since fs.readFileSync is used in browser-pack.
These are the errors after webpack build was completed:
WARNING in ./node_modules/browserify/index.js 396:16-30
Critical dependency: the request of a dependency is an expression
WARNING in ./node_modules/module-deps/index.js 302:20-32
Critical dependency: the request of a dependency is an expression
# ./node_modules/browserify/index.js

Babel recursive transpilation

Scenario
Consider the following directory structure
/views
/one.js
/two.js
/components
/Header.js
/Footer.js
/other
...
I need to transpile the /views directory with Babel. I am doing it programmatically but the equivalent cli command would look like something like this:
babel views --out-dir .views
But files in the /views directory depend on files in other directories, i.e.
/*
views/one.js
*/
const Header = require('../components/Header');
...
Given this dependency, I also need /components/Header.js to be transpiled.
Question
How can I use Babel, possibly with another library, to only transpile the specified directory and any recursive dependencies without transpiling the entire codebase (e.g. /other, etc.)?
There are probably multiple options for getting dependency graphs in Node. You can use node-dependency-tree to get the dependency graph you want to transpile with babel. Madge would be another possible option (uses dependency-tree internally).
How does it work?
Dependency tree takes in a starting file, extracts its declared dependencies via precinct, resolves each of those dependencies to a file on the filesystem via filing-cabinet, then recursively performs those steps until there are no more dependencies to process.
When using dependency-tree the toList method
Returns a post-order traversal (list form) of the tree with duplicate sub-trees pruned.
This is useful for bundling source files, because the list gives the concatenation order.
Note: you can pass the same arguments as you would to dependencyTree()
The two arguments used by toList are
filename The path to the file containing the initial dependency, i.e. the dependency graph's entry point. This is used by the module filing-cabinet.
directory The path to all the files, i.e. the root for resolving dependencies. This is also used by the module filing-cabinet.
This build script is using CommonJS modules, Node v16.16.0, and Babel 7.19.3. I'm sure you can convert this to ES modules with no issues, or be Promise based if you prefer.
build.js
const fs = require('node:fs')
const { dirname, resolve } = require('node:path')
const dependencyTree = require('dependency-tree')
const babel = require('#babel/core')
dependencyTree.toList({
filename: './views/one.js',
directory: './views'
}).forEach(path => {
const basepath = path.split('views/')
const filepath = resolve('./.views', basepath[1])
const directory = dirname(filepath)
fs.mkdirSync(directory, { recursive: true })
fs.writeFileSync(
filepath,
babel.transformSync(fs.readFileSync(path).toString()).code
)
})
node build.js

How do I require something in root project directory from inside node package library?

I wanna create a node package modules, but I have difficulty to require a file from root project directory to use inside my node package module I created.
If I have directory structure like this
- node_modules
- library_name
- lib
- index.js
- bin
- run.sh
- config.js
If the run.sh called, it will run index.js. Inside index.js, how do I resolve to root directory which later I can require config.js inside index.js?
Package binary can accept configuration path explicitly as an argument.
If package binary doesn't run as NPM script, it shouldn't rely on parent project structure.
If package binary runs via NPM script:
"scripts": {
"foo": "library_name"
}
This will set current working directory to project root, so it could be required as:
const config = require(path.join(process.cwd(), 'config'));
Both approaches can be combined; this is often used to provide configuration files with default locations to third-party CLI (Mocha, etc).
If you're in index.js and config.js is in the directory above node_modules in your diagram, then you can build a path to config.js like this:
const path = require('path');
let configFilename = path.join(__dirname, "../../../", "config.js");
__dirname is the directory that index.js is in.
The first ../ takes you up to the library_name directory.
The second ../ takes you up to the node_modules directory.
The third ../ takes you up to the parent of node_modules (what you call project root) where config.js appears to be.
If you really want your module to be independent of how it is installed or how NPM might change in the future, then you need to somehow pass in the location of the config file in any number of ways:
By making sure the current working directory is set to the project root so you can use process.cwd() to get access to the config file.
By setting an environment variable to the root directory when starting your project.
By passing the root directory in to a module constructor function.
By loading and passing the config object itself in to a module constructor function.
I create module same your module.
And I call const config = require('../config'), it work.

Javascript: get package.json data in gulpfile.js

Not a gulp-specific question per-se, but how would one get info from the package.json file within the gulpfile.js; For instance, I want to get the homepage or the name and use it in a task.
This is not gulp specific.
var p = require('./package.json')
p.homepage
UPDATE:
Be aware that "require" will cache the read results - meaning you cannot require, write to the file, then require again and expect the results to be updated.
Don't use require('./package.json') for a watch process, as using require will resolve the module as the results of the first request.
So if you are editing your package.json those edits won't work unless you stop your watch process and restart it.
For a gulp watch process it would be best to re-read the file and parse it each time that your task is executed, by using node's fs method
var fs = require('fs')
var json = JSON.parse(fs.readFileSync('./package.json'))
This is a good solution #Mangled Deutz. I myself first did that but it did not work (Back to that in a second), then I tried this solution:
# Gulpfile.coffee
requireJSON = (file) ->
fs = require "fs"
JSON.parse fs.readFileSync file
Now you should see that this is a bit verbose (even though it worked). require('./package.json') is the best solution:
Tip
-remember to add './' in front of the file name. I know its simple, but it is the difference between the require method working and not working.
If you are triggering gulp from NPM, like using "npm run build" or something
(This only works for gulp run triggers by NPM)
process.env.npm_package_Object
this should be seprated by underscore for deeper objects.
if you want to read some specific config in package.json like you want to read config object you have created in package.json
scripts : {
build: gulp
},
config : {
isClient: false.
}
then you can use
process.env.npm_package_**config_isClient**

Categories

Resources