Document how to import this module
Closed this issue · 18 comments
I download form-data-json.js
into my package and try to import this module:
const FormDataJson = require('../common/form-data-json.js');
export function ajaxForm(form) {
const formData = FormDataJson.toJson( form );
But get error: FormDataJson is not defined
How to import this module?
Hm, do you mean this feature? https://www.digitalocean.com/community/tutorials/js-modules-es6
This have import/export
but not require
as you have suggested.
This lib does support IE11, i doubt that it is possible to support ES6 modules because of syntax errors in older browsers.
I download and copy form-data-json.js
into my project.
I use webpack and at my main.js
I do this:
https://github.com/brainfoolong/form-data-json/tree/v2-dev#installation
const xx = require( "./common/form-data-json.js" );
window.addEventListener("DOMContentLoaded", (event) => {
debugger;
xx.toJson();
});
const webpack = require("webpack");
const path = require("path");
const glob = require("glob");
const config = require("./gulp/config");
module.exports = {
entry: toObject(glob.sync(config.scripts.srcScripts)),
output: {
filename: "[name].js",
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: `babel-loader`,
},
],
},
mode: config.mode.isDevMode ? "development" : "production",
devtool: config.mode.isDevMode ? "eval-source-map" : "none",
};
function toObject(paths) {
const entry = {};
paths.forEach(function (p) {
const name = path.basename(p, ".js");
entry[name] = p;
});
return entry;
}
As far as I can understand, this file should be loaded as CommonJS and not ES module.
But it is loaded as ES.
So I need not only require
as described here: https://github.com/brainfoolong/form-data-json/tree/v2-dev#installation
The problem here probably because I try to load CommonJS module from my ES modules
Finally I resolve this.
We should be aware of: https://webpack.js.org/api/module-methods/
Actually webpack would enforce the recommendation for .mjs files, .cjs files or .js files when their nearest parent package.json file contains a "type" field with a value of either "module" or "commonjs". Please pay attention to these enforcements before you read on:
* .mjs or .js with "type": "module" in package.json
No CommonJS allowed, for example, you can't use require, module.exports or exports
File extensions are required when importing, e.g, you should use import './src/App.mjs'
instead of import './src/App' (you can disable this enforcement with Rule.resolve.fullySpecified)
So because I copy form-data-json.js
into my project as .js
then webpack load it as ES module. Which cause error above.
So I must copy file as .cjs
and EXPLICITLY import it with EXENTION!!! eg:
import FormDataJson from "./form-data-json.cjs";
Ok. I think there is a confusion of the NPM
part in the readme. This is meant only for NodeJS, i'll update the description.
When you use webpack, you should pack the original js
file directly in your bundle that is integrated on your page. This is how most JS libraries work, i guess? Loading it afterwards with an import is not supported out of the box.
When you use webpack, you should pack the original js file directly in your bundle that is integrated on your page.
Yes, I also speak about bundle
It is not packed because import FormDataJson from "./form-data-json.js";
is loaded as ES module and fail.
But if I rename it to .cjs
it works well. This is because your module is CommonJS module ;-)
So I suppose to see a section at documentation for webpack, eg: If you use webpack you must rename module as .cjs
... bla-bla-bla
Hm.... How do you add other libraries in webpack? As far as i understand webpack from the docs correctly, you can integrate any JS files directly in the bundle (via webpack config). Here you can include any JS file you want.
This is how it is supposed to work with any 3rd party library which is globally available (like jquery, vuejs, svelte, etc...), isn't it?
Only when you use a library that supports module behaviour AND if you want specifically the import
feature (which i don't suggest for this library, because probably of multiple imports of the same file), without packing it directly in the webpack config, than you have to rename it to .cjs
.
I see, a very special case. I'll add a readme entry about using this lib as an import module.
I reread my messages and probably they could look a bit aggressive because of bold and capital letters. Yes, this emotions but emotion like holiday, celibrate, hoooray, hooray etc ;-)
When I build my project then webpack will put all src/js/**/*js
files into one file dist/main.js
Scripts which make use of form-data-json
do import. For example file js/forms/ajaxForm.js
first line is:
import FormDataJson from "../common/form-data-json.cjs";
The important thing here is only extension. It must be .cjs
. All other stuff will be handled automatically by webpack.
I don't understand them as offense, no problem.
Isn't FormDataJson available without any import in your case, as it is already in the main.js
? (F12 -> console.log(FormDataJson)
But probably you do try to call it before they included in the code?
PS: This library is automatically in global namespace without import, as soon as you have loaded/packed it in a file that is loaded via <script>
tag.
nope, it is not available global and it is OK. FormDataJson
is scoped to module which make import
. When I want to make it globally available to all my modules, then I must expose it or do webpack.config.js
similar jQuery:
And when I include my resulting bundle js/main.js
from my html, FormDataJson
is still not available globally. I suppose this is feature of webpack.
When I include module at html file as <script src="js/form-data-json.js"></script>
then Yes, FormDataJson
is available globally
Here is how it work if I load form-data-json.js
directly (last case above)
Ahhh, ok now i understand. Webpack capsulate it and only the config Webpack.ProvidePlugin
make it into the global namespace.
If this work (if you can confirm), this should be the recommended way, without renaming files and without import.
For sure, i'll add both ways into Readme, albeit a webpack user probably already know the tricks to expose 3rd party libs.
probably webpack users know that =) Unfortunately I do not know Webpack.ProvidePlugin
way
I am more backend developer and work with library since insofar
Can you try adding the following with your plugins
config?
new webpack.ProvidePlugin({
FormDataJson: 'FormDataJson'
})
Hm. Ok thx for trying. I don't have other ideas :)
This works
module.exports = {
entry: toObject(glob.sync(config.scripts.srcScripts)),
output: {
filename: "[name].js",
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: `babel-loader`,
},
{
test: require.resolve("jquery"),
loader: 'expose-loader',
options: { exposes: [ '$', 'jQuery' ] },
},
{
test: path.resolve(path.join(__dirname, 'src/js/common/form-data-json.cjs')),
loader: 'expose-loader',
options: { exposes: 'FormDataJson' },
},
],
},
Ok. I decided to not add a readme in the library description for this, as webpack has it's own rules and documentation on their side. This library does work the same as every other library, so a webpack user should search for their specific solution in the docs from the bundler itself.
Otherwise there is no end. We for example use another bundler internally, which has it's own rules how to integrate this library. But that's not part of the library documention.
Thanks for your input anyway.
NPM is an exception in the readme, as i officialy have an NPM module entry in the offical NPM registry.