How does node.js require('xxx') knows which javascript file is the main entrance in xxx package? - npm

I'm trying to write a node module myself and publish it.
Assume the dir looks like below:
root/
a.js
b.js
c.js
package.json
now a.js and b.js are required in c.js, and I want c.js to be the package interface when other developers require my package. How to specify that? I don't have a clue.
When my package is required, how does npm knows which js file is the main entrance?

It can be specified as main field in package.json: "main": "c.js"
https://docs.npmjs.com/files/package.json#main
By default index.js from package folder would be used.
https://nodejs.org/api/modules.html#modules_folders_as_modules

Related

How to handle project assets with NPM together with SonataAdminBundle?

Since version 4.x of SonataAdminBundle all assets are handled using NPM and WebPack.
In my project I also have some assets and JS libraries and I'm also using NPM and WebPack.
What should I do in this case? For example, SonataAdminBundle uses libraries such as jQuery, Bootstrap, but I also use them (in my package.json).
One of the ideas that came to my mind is to import the main "app.js" file (vendor/sonata-project/admin-bundle/assets/js/app.js) from SonataAdminBundle which contains all the required components to run to my main "app.js" file and then import my other additional libraries and assets. Next, I would then copy all the dependencies from the SonataAdminBundle package.json file (vendor/sonata-project/admin-bundle/package.json) and paste it into my package.json file.
I am not sure if this approach is correct.
The downside of this solution would be to compare the package.json files after each update of the SonataAdminBundle library and apply any changes.
Do you have other ideas to solve this problem?

How to access the dependency versions in a Create-React-App

In a create-react-app i would like to access some properties of the package.json and show those to the user in the browser. Like the version of the app and the version of some of the dependencies specified in the package.json.
How would I access those properties, without importing and exposing the whole package.json to the client?
Executing npm run build on the create-react-app provides a production bundle in the ./build directory.
Solution 1:
The way it works it does not expose the rest of the package.json content to the production bundle when making a destructured import. (E.g. previous answer from Devchris)
import { dependencies } from './package.json';
Solution 2:
By extending the npm scripts it is possible to read and expose the package.json into the node environment and read it from there at build time (https://create-react-app.dev/docs/adding-custom-environment-variables)
process.env.REACT_APP_DEPENDENCIES
Note: The variable must start with 'REACT_APP_'
What you can do is:
import { version, dependencies } from './package.json';
this will give you all dependencies and the version of your package.json in your js code. Keep in mind that your path to the package.json file might be different.

How to turn multiple vue components into one single npm package?

I was told by the project manager at the company I work for to take all the global components of a vue project we're working on and turning them into a single npm package that anyone working on the project can import and start using. essentially I have to take the global components and turn them into a component library like vuetify which is installed using npm and than imported from node modules directory.
I was wondering if you guys could point me in the right direction on how to achieve this. thanks in advance.
So, regardless of the implementation, the main thing you need is following this guide on how to create an npm package
https://docs.npmjs.com/creating-and-publishing-private-packages
Then
You create an src folder.
In the src, you will create a folder named "components" with all your -duh- components.
In the src folder, you will also create an index.js file, from there you will export your components.
export { default as VDataTable } from './components/VDataTable.vue'
// ...etc
Option1
If you use a bundler for your projects, and you know by a fact that all your codebases will use a bundler, you can simply create a folder with a package.json.
In your package.json then you will
"module": "src/index.js",
"main": "src/index.js"
In this scenario, you are letting your main project bundler (which is using the package) transpile all the packages for you, (babel, single file components)
Option 2
In case you have absolutely no clue of the nature of the projects which can use your library you will need a bundler for your components.
An example can be Rollup.
I suggest these 2 guides.
https://rollupjs.org/
https://rollup-plugin-vue.vuejs.org/
Long story short, Rollup will transpile for you the files you requested (js and css), and you will have to make them available from your package.json
"module": "src/dist/library.esm.js",
"main": "src/library.common.js"
And then you can release your package. Possibly privately or you might get fired :P

What's the correct approach for re-building a npm package within my own project?

Presentation:
I built an admin template (css + js) and I uploaded it to npm. The package contains the compiled css/js files in the "dist" folder, and the scss files in the "build" folder. The package has several dependencies which are listed as devDependencies in the package.json:
"devDependencies": {
"datatables.net": "^1.10.19",
"dropzone": "^5.5.1",
"laravel-mix": "^4.0.13",
...
}
There are no dependencies, which I assume is correct because I directly use the compiled css/js (the js is just jQuery code).
There's an admin.scss file which has all the imports:
#import 'abstracts/variables';
#import
'~datatables.net-bs4/css/dataTables.bootstrap4.min.css',
'~easymde/dist/easymde.min.css',
'~flatpickr/dist/flatpickr.min.css',
'~jasny-bootstrap/dist/css/jasny-bootstrap.min.css',
'~selectizebootstrap/dist/css/selectize.bootstrap4.css';
#import
'components/alerts',
'components/cards';
I'm using the admin package in a PHP project (Laravel). The admin package is included in the devDependencies of my PHP project. The admin.css file is included in the php.scss file:
#import '../../node_modules/admin-template/dist/css/admin.css';
The problem:
I need to change some variables of the admin.scss file. So, instead of include the compiled css I need to include the scss:
#import '../../node_modules/admin-template/build/scss/admin';
If I do that, I get errors because the admin template devDependencies are not installed in my node_modules.
If do a npm install within the admin template folder, a node_modules folder is created and all the dependencies are installed inside that folder.
But the errors doens't go away, I think is because of the tilde used in the imports of the scss file: #import '~datatables.net-bs4/css/dataTables.bootstrap4.min.css'. It's looking for the files in the root folder (not within the package).
What should I do?
Add all the admin template devDependencies as devDependencies of my PHP project? Doesn't seems right.
List the admin template devDependencies as dependencies, so when I install the package, all the dependencies get installed too? Doesn't seems right either, those are devDependencies.
Remove the tilde ~ off all the #imports in the admin.scss file? So if I need to include directly the scss I need to do an npm install within the package. And if I already have some of that packages installed in my node_modules, they'll be twice.
Any other options?
Short answer, also put them into "optionalDependencies" field of admin-template/package.json.
This way, when you:
cd php-project
npm install admin-template
# or simply `npm install` if it's already in "dependencies"
"optionalDependencies" of admin-template, like datatables.net-bs4 will be installed into top-level node_modules folder. Plus, "optionalDependencies", the semantic seems pretty damn right to me.
Now if you really care about the install footprint for users who only use .css in your package, then unfortunately, no easy way to do it.
You inevitably require users of .scss to do some extra work. You either provide a guide for them on how to do it manually, or you can provide a script to automate that.
One possible solution is you also provide a bin file.
admin-template/bin/admin-template-enable-sass.js # or .sh if you prefer
// package.json
{
"bin": "bin/admin-template-enable-sass.js"
}
This way, when user npm install admin-template, that bin file is symlinked to top-level node_module/.bin, making it runnable with npx cli command.
Now your .scss advance user can simply type:
npx admin-template-enable-sass
to let your script take care things for them.

How to write a multi-file NPM package with Brunch

I have a multi-file project, with ES6 style exports and imports.
I'm using Brunch to concatenate these files into 1 main.js file that will serve as the main for an NPM package.
To specify the API of my package, I need to have exports in main.js. But when Brunch concatenates my js files, I am worried that (1) exports that are meant for internal imports and (2) exports meant for my API will both look the same.
Looking at the generated main.js file it seems like the exports I write in my source code get wrapped into modules, but none of these are top-level exports like the ones needed for NPM packages.
How can I let NPM distinguish between these two types of exports? Specifically, how can I have exports in the main.js file generated by Brunch concatenation?
Brunch is not designed for writing libraries, but rather for building apps.
I don't need to concatenate files at all to publish them to NPM, so instead I have used Babel with React and ES6 presets to transform my ES6 .jsx files to ES5 .js files.
I then make one file (eg. main.js) where I export my library and set that as the main in package.json.
I can then use Brunch to create an app with the React skeleton (brunch new -s brunch/with-react), npm install <my-package>, and import my library within my app.