Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Importing UMD style module with ES6, Webpack, and Babel

I have found a few StackOverflow questions related to this but none that match nor fix my problem.

I am writing a library in ES6 that is intended to be used in the browser and on the server. I have found a few HTTP request libraries that can be use on the server or browser (popsicle, axios). I have successfully used these libraries in both places but am having some issues when importing them in my source and using the outputted webpacked file.

My ES6 source file where I am importing the axios library is

import axios from 'axios';

export default {
    go: function() {
        return axios.get('http://www.google.com');
    }
};

My webpack config is

var webpack = require('webpack');
var UglifyJsPlugin = webpack.optimize.UglifyJsPlugin;
var WebpackNotifierPlugin = require('webpack-notifier');
var path = require('path');
var env = require('yargs').argv.mode;

var libraryName = 'library';
var source = '/src/test.js';

var plugins = [],
    outputFile;

if (env === 'build') {
    plugins.push(new UglifyJsPlugin({
        minimize: true
    }));
    outputFile = libraryName + '.min.js';
} else {
    outputFile = libraryName + '.js';
    plugins.push(new WebpackNotifierPlugin())
}

var config = {
    entry: __dirname + source,
    devtool: 'source-map',
    output: {
        path: __dirname + '/lib',
        filename: outputFile,
        library: libraryName,
        libraryTarget: 'umd',
        umdNamedDefine: true
    },
    externals: {},
    module: {
        loaders: [{
            test: /(\.jsx|\.js)$/,
            loader: 'babel',
            exclude: /(node_modules|bower_components)/
        }, {
            test: /(\.jsx|\.js)$/,
            loader: "eslint-loader",
            exclude: /node_modules/
        }]
    },
    resolve: {
        root: path.resolve('./src'),
        extensions: ['', '.js']
    },
    plugins: plugins
};

module.exports = config;

As you can see I am setting the libraryTarget to umd and umdNamedDefine to true

And my .bablerc is

{
  "presets": ["es2015"],
  "plugins": ["add-module-exports", "babel-plugin-add-module-exports"]
}

I am able use my library in the browser by including it in a script tag but I am not able to use it when importing with node. I get an XMLHttpRequest is not defined. The axios library says it uses XMLHttpRequest when on the browser and http when running in node but for some reason it is not detecting it is being run on the server. I am having this issues with a few UML libraries so believe it is not the specific package. Also, since I can use these libraries in node ES5 without running webpack or babel I am led to assume it is a configuration issue with webpack.

How can I import these UMD style libraries in ES6 and generate a library with Webpack and Babel that can be used on the server and browser?

like image 313
Jake Runzer Avatar asked May 17 '16 06:05

Jake Runzer


People also ask

Does webpack use ES6 modules?

This section covers all methods available in code compiled with webpack. When using webpack to bundle your application, you can pick from a variety of module syntax styles including ES6, CommonJS, and AMD.

How import works in webpack?

The imports loader allows you to use modules that depend on specific global variables. This is useful for third-party modules that rely on global variables like $ or this being the window object. The imports loader can add the necessary require('whatever') calls, so those modules work with webpack.

Does webpack use CommonJS?

Webpack supports the following module types natively: ECMAScript modules. CommonJS modules.


1 Answers

To make your package as small as possible I'd recommend using the Fetch API. A UMD library has the three types of consumers where fetch comes in handy;

  • Node.js - has not implemented but can use node-fetch to polyfill common behaviour using only node libraries (no heavy dependencies like superagent, unirest and axios etc - these add security concerns as well as bloat!).
  • Browser - Fetch is a WHATWG standard and is available in most modern browsers but might require an npm package such as whatwg-fetch to polyfill older browsers
  • Isomorphic/Universal - the same javascript running in browser and node.js which you find in progressive web apps.They need to use a library called isomorphic-fetch to load either whatwg-fetch or the node.js version of fetch.

It should be handled by the projects consumer though so README should include instructions to each of the three types of users above.

Node.js and isomorphic instructions are basically as below.

require(‘node-fetch’); // or require(‘isomorphic-fetch’)
const MyUMDLibrary = require('my-umd-library');
const myUMDLibrary = new MyUMDLibrary();

For browsers using the script from cdn they could also load a fetch polyfill before https://cdnjs.cloudflare.com/ajax/libs/fetch/2.0.3/fetch.js.

I'd suggest using rollup for a UMD library (see a working example I've contributed before for a UMD library) but Webpack shouldn't be a problem either. Rather than trying to include the 'axios' dependency within your application with Fetch you can leave it out and allow your users to decide how they will load the package (i.e. module loader, script, require).

like image 53
sidhuko Avatar answered Oct 12 '22 03:10

sidhuko