Importing UMD style module with ES6, Webpack, and Babel
Asked Answered
R

1

12

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?

Repeated answered 17/5, 2016 at 6:57 Comment(4)
You shouldn't be using Webpack on the server-side. That's the core of your issue and not related to ES6 or Babel or anything else you mentioned. Try without Webpack.Chaliapin
But then how should I create the minified library which I can then publish to npm?Repeated
You don't. That's a terrible practice. Node doesn't need minified files, browsers do. Minification is a job for bundlers. There's many reasons for this, but for one - you're opting out of versioning and dependencies (you can't dedupe now). Of course, you can use Webpack for node-code, but make sure you enable node mode first. You'll have to look it up though.Chaliapin
Webpack is actually fine to use now. They have options to run as a package loader but you might find using rollup easier to generate a UMD packageKeyhole
K
1

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).

Keyhole answered 5/1, 2018 at 10:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.