I have to publish a npm package that is written with Flow and compiled using babel.
What I did was I compiled all my source files. Then I copied compiled files from dist/ and put them into some other directory. I also put package.json there and edited it and then I published the package on npm.
I can then normally install project and require it my project. However when I run my project, it throws error that I need to require babel-core and babel-polyfills (install them as dev-dependencies). The problem is since my new project only requires my own package and does not use babel or something like that, so I see no point in requiring babel dependencies in my new project.
My question is, how can I package my library that is written with Flow and compiled by babel, so that I can then use this package in other places without requiring babel.
Did you add main and files into your package.json?
https://docs.npmjs.com/files/package.json#main
https://docs.npmjs.com/files/package.json#files
Your files should probably be
"files": [
"dist/**"
],
Also to prevent Users who install your package from needing to install the transpilers (i.e babel) add them into your devDependencies
Directly from the https://docs.npmjs.com/files/package.json#dependencies
Please do not put test harnesses or transpilers in your dependencies object. See devDependencies, below.
Also to add flow to your dist add https://github.com/AgentME/flow-copy-source
flow-copy-source -v src dist
The problem was in using incorrectly defined preset
In my babelrc I only had defined
preset: "env" without specifying that it needs to run on node 8 and higher, since the code used async.
Therefore i defined preset as:
preset: ["env", {
targets: {
"node": "8.9.1"
}
}
And the asnyc functions compiles correctly.
Also, thanks to #Kenneth I used flow-copy-source to add type to my library, so it can be seen in intelisense.
Related
tl;dr: How to use babel 7.10 as a complete beginner for frontend js files in a fullstack node app?
I am trying to use the newest version of Babel (7.10.5) to compile the JS files of my website and this is my first time using Babel. Since the documentation of babel doesn't seem to be fully updated or because I'm too dumb to get it.
I only produce JS files with either "require", which the browser doesn't understand, or with some "import" of some babel file that the browser doesn't see.
I have no clue what I should be doing, I have tried with a babel.config.json file as well as a .babelrc file. I installed and uninstalled all kinds of packages and plugins and whatever, but nothing seemed to work.
I don't care about module size or anything advanced, I just want my simple website written with es6 to work in all browsers, to use es5 basically. I know that I need #babel/cli #babel/core and #babel/preset-env and that I need some kind of config file and then I wanna run it via the command line. What's the easiest way to do this?
As a side note, I am not using any framework, just plain old vanilla JavaScript
Sorry if this question is super dumb or if it's badly asked. I can't show any code, because I don't
1, install dependencies:
npm i #babel/cli #babel/core #babel/preset-env
2, add .babelrc:
{
"presets": [
"#babel/preset-env"
]
}
3, edit package.json, in this example, make sure all your source files in "src" dir
//package.json
{
"scripts": {
"build": "babel src --out-dir dist"
},
4, run script, generated files will be in "dist" dir
npm run build
I added the type: module but that didn't help.
I am trying to run mocha or jest tests that use import and export for the source files.
The existing questions about this have specifics that are different from mine and I also find them confusing to follow for someone with my specific situation, especially since I have developed a specific answer with details not relevant to the existing questions, but relevant to other people in my situation.
In the past, you could not use ES modules (i.e. import/export) in Node without transpiling your code using Babel. However, support for ES modules in Node is now a reality, and both Jest and Mocha have also recently added support for using ES modules natively.
It takes more than just adding "type": "module" to your package.json, however.
Steps for using native ES Modules in Jest
As already mentioned, add "type": "module" to your package.json
Install either jest-environment-node or jest-environment-jsdom-sixteen to your development dependencies. For example:
$ npm i -D jest-environment-node
Update the Jest configuration in package.json and add the testEnvironment setting. For example:
"jest": {
"testEnvironment": "jest-environment-jsdom-node"
}
If you are using a version of Node earlier than 13.2, then you will need to add two additional flags when running Node: --experimental-modules and experimental-vm-modules. I use npx to execute the commands, although it's a little verbose:
$ npx --node-arg=--experimental-modules --node-arg=--experimental-vm-modules jest
This will run all your Jest tests using the appropriate Node flags. I'd recommend making this your test script in package.json if this is the way you go.
Now you should be able to use import/export without Babel!
One last important point: when using native ES modules in Node, you have to use the entire import path to your local modules, including the file extensions. For example:
import lib from "./my/lib.js"
Here is the Node documentation on native ES modules, if you want to read about this in more detail: https://nodejs.org/dist/latest-v14.x/docs/api/esm.html
I'd also recommend reading through this Github issue for more details on the Jest implementation of native ES modules: https://github.com/facebook/jest/issues/9430
Per the Jest documentation, if you make sure babel-jest is installed and supply your Babel configuration per the Babel documentation, in a config file or package.json e.g.:
.babelrc.json
{
"presets": [
"#babel/env"
]
}
Then babel-jest will pick it up automatically and you don't need to explicitly pre-build the files to test them. This also means you don't have to set flags on the command line when calling Babel.
Note that if you do want to explicitly pre-build, I'd recommend:
Using a pre<script> script rather than having multiple steps in one line; and
Re-using the build script so you don't have to make changes in two places.
In your case:
"scripts": {
"build": "babel src/ --out-dir lib",
"pretest": "npm run build",
"test": "jest lib/*.test.js"
}
You need to use a compiler and then use the compiled files when running tests.
Many of the references say to add type: module but don't say much more.
To be clear, the basic message:
SyntaxError: Cannot use import statement outside a module
is because you are using import/export and you are trying to run the files directly without compilation.
The mindshift here is getting used to editing the files in one directory and running the tests in another. Alternatively, some solutions offer "in'flight" compilation so this detail is essentially hidden and only the source files are used.
There are a few different approaches to doing this depending on specific needs. Here is one of the simplest approach I've found so far, using Babel for the compilation step:
Install babel npm install babel --save-dev
Add babel commands in package.json scripts, for example:
"scripts": {
"test": "babel src/ --out-dir lib --presets=#babel/env; jest lib/*.test.js",
"build": "babel src/ --out-dir lib --presets=#babel/env"
}, // this was for jest but you can use mocha, etc as needed
// Note that using preset this way eliminates the need for a specific .babel.config.json file
Now, if you run:
jest .
you get SyntaxError: Cannot use import statement outside a module, but if you run npm t you get
Successfully compiled 2 files with Babel.
PASS lib/app.test.js
All tests
✓ Canary test (2ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Going forward, just remember to:
Edit files in src/
Run tests in lib/
I was learning webpack and babel and majority of tutorials on YouTube teach to install webpack and babel separately. But I tried to install webpack only without installing babel( and uglify.js). So, I used webpack then it automatically uglified and changed my ES6 code into ES5 how is that possible?. The question is Does webpack 4 use uglify.js and babel behind the scenes even if I do not install them manually?
Webpack does not contain Babel or uglify by default. These are contained within the loaders. These are seperate npm packages you need to install used in the configuration.
this question can give you an idea of how these are configured:
In order to check yourself if a package contains another package you can easily make an empty folder and run one of the following:
npm install --save webpack#4
yarn add webpack#4
and then check the 'yarn.lock' or 'package-lock.json' file and search for the dependency.
Situation: You have a JS module that you wrote yourself or 3rd party. It may have npm dependencies. It may be written with ES6 syntax and may use new ES6 (or 7, etc) features. You want to use it on Rhino.
The problem: Rhino supports require()ing files, but it does not have OOTB support for npm. It only supports JavaScript 5 syntax and features.
How can I run my pretty new JS stuff on Rhino?
You can bundle your JS into a single file and convert it to JS 5.
Solution: Babel supports JS syntax conversion. core-js polyfills fill in missing ES6 features. Browserify supports bundling up a dependency tree (including npm dependencies) into a single standalone file.
The Details: Easier said than done. Read on for a step-by-step guide.
Create a "bundler" directory. Later on, we will put mymodule.js in it, but let's hold off on that.
cd into your bundler directory and run npm init to create a package.json file.
Add your build command to the "scripts" section of package.json
:
"build": "browserify mymodule.js -t babelify --standalone mymodule -o bundle.js"
browserify mymodule.js means that browserify is going to bundle up mymodule.js and all its dependencies. -t babelify means that babel will transpile the code, converting ES6 things to 5. --standalone mymodule means that the things your module exports via module.exports will be preserved. -o bundle.js means that the output file will be bundle.js. You'll want to rename this file back to your module's name when you add it to Rhino.
Create the babel config file babel.config.js
:
module.exports = function (api) {
api.cache(true);
const presets = [
[
"#babel/preset-env",
{
useBuiltIns: "entry",
corejs: 3,
}
],
];
const plugins = [];
return {
presets,
plugins
};
};
The newest version of corejs is currently 3, but use a newer version if there is one. The useBuiltins can be "usage" instead, which may be better depending on your situation.
Install things
:
npm install --global browserify
npm install --save-dev babelify #babel/core #babel/preset-env
npm install core-js
This completes the setup of your "bundler", per se. You can save what you have so far for future use. The following steps now show how to use this bundler on one of your modules...
Put your module file (let's call it mymodule.js) and all of its dependencies into the bundler directory. This includes running npm install ... to install all of mymodule.js's npm dependencies.
Add the line
:
import "core-js/stable";
to the top of mymodule.js. This imports the needed polyfills. To reduce the filesize, you can import the specific JS features that your module (and its dependencies) actually use. For example, import "core-js/stable/number/is-nan"; to import the isNaN method on the Number class. It may be difficult though to know what you specifically use. That's why the "usage" option in tandem with browserslist may be the best way to slim. See core-js for more.
For example, your file may look like:
import "core-js/stable";
import mylib from "my-3rd-party-lib";
module.exports = mylib;
if it is nothing more than a 3rd party library that you want to use in Rhino. If it's a module you wrote yourself, then there will be a bunch of code between the core-js import at the top and the module.exports at the bottom.
Finally, run the build command you wrote in step 4
:
npm run build
You should now have a file called bundle.js. You should be able to copy that file into the place where the Rhino engine will find it, and it should work.
cp bundle.js /path/to/where/to/place/dist/file/mymodule.js
Happy coding.
I wrote an npm package blokus which use ES6 syntax.
I used create-react-app to start a project web-blokus, which depends on blokus.
I can run npm start with no errors, and view my web-blokus app in my browser, and it has all the functionality from using the blokus package.
The problem is that I get an UglifyJS error when running npm build.
static/js/main.8afd34e2.js from UglifyJs
SyntaxError: Name expected [./~/blokus/blokus/blokus.js:3,0]
It appears there is a known situation with UglifyJS not supporting ES6 dependencies (a few relevant issue threads here and here). But I read through these threads as well as a handful of others and I was left pretty confused as to what was planning to be updated and what people were doing as workarounds.
So I wanted to
1) confirm that create-react-app will not work out of the box (once you go to npm build) if your app has any ES6 dependencies
2) ask what people are doing to fix / bypass the issue (do I have to eject, and swap something in for UglifyJS?)
Since create-react-app and ES6 are now so popular, I assume I'm either misunderstanding the limitation, or a standard method of dealing with this limitation is discussed and known.
You can't use ES6 code with create-react-app, or most build systems.
npm packages shouldn't result in ES6 code because of existing tooling, and to a lesser extent, older node versions.
To set up your package, assuming the ES6 code is in the src directory:
npm install --save-dev babel-core babel-cli babel-preset-latest
.babelrc
{
"presets": ["latest"]
}
package.json
"main": "./lib",
"scripts": {
"build": "babel src --out-dir lib"
}
Then do npm run build before publishing.
Create a .gitignore with 'lib' in it, and a .npmignore that's empty. The .npmignore needs to exist.
You can run your tests on the src directory (or lib, doesn't much matter).