Roberto
Roberto

Reputation: 257

Javascript modules with Webpack

I'm trying to refactor client javascript in my nodejs/express application using CommonJS + Webpack modules.

With Webpack I build a 'bundle.js' made of two js files where I defined the two modules following CommongJS syntax. But on window.onload of the page I get a nice 'TypeError: moveTo.logHelloWorld is not a function" error.

Where am I wrong?

Webpack configuration:

var webpack = require('webpack');
var path = require('path');

module.exports = {
  entry: ['./public/js/common.js', './public/js/moveTo.js'],
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'bundle.min.js'
  },
  plugins: process.env.NODE_ENV === 'production' ? [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.UglifyJsPlugin()
  ] : []
}

moveTo.js

var moveTo = {};

console.log("moveTo.js loaded...");

moveTo.logHelloWorld = function(){
  console.console.log("Hello World logHelloWorld() from moveTo client Javascript!");
};

module.exports = moveTo;

moveTo.handlebars

<div>MoveTo</div>
<script type="text/javascript">
  window.onload = function(){
    console.log("ON LOAD...");
    moveTo.logHelloWorld();
  }
</script>

and finally in the main template I included the bundle.js built with Webpack:

<script src="/bundle.min.js" type="text/javascript"></script>

And this is the error I got:

enter image description here

UPDATE: How to use multiple client js files Suppose I would like to add another test.js file with its own module like so:

test.js

var test = {};

console.log("test.js loaded...");

test.logHelloWorld = function(){
  console.log("Hello World logHelloWorld() from TEST client Javascript!");
};

module.exports = test;

And then in Webpack config:

var webpack = require('webpack');
var path = require('path');

module.exports = {
  entry: ['./public/js/common.js', './public/js/moveTo.js', './public/js/test.js'],
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'bundle.min.js',
    library: ["moveTo", "test"] //This is not working.
  },
  plugins: process.env.NODE_ENV === 'production' ? [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.UglifyJsPlugin()
  ] : []
}

How may I get this to work?

UPDATE: This is what i get using the suggested webpack configuration enter image description here

#LAST UPDATE#

Apparently there is no way to have a single bundle.js and get it to work with different javascript files. This is the only thing I reached so far with the precious help of @hazardous:

webpack.config.js

var webpack = require('webpack');
var path = require('path');
// ['./public/js/common.js', './public/js/moveTo.js', './public/js/test.js'],
module.exports = {
  entry: './public/js/t3toolbox.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'bundle.min.js',
    library: ["t3toolbox", "[name]"]
  },
  plugins: process.env.NODE_ENV === 'production' ? [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.UglifyJsPlugin()
  ] : []
}

t3toolbox.js

var t3toolbox = {}; // Global App NameSpace
var test = require('./test.js');
var moveTo = require('./moveTo.js');

t3toolbox.moveTo = moveTo;
t3toolbox.test = test;

module.exports = t3toolbox;

moveTo.js

var moveTo = {};

console.log("moveTo.js loaded...");

moveTo.logHelloWorld = function(){
  console.log("Hello World logHelloWorld() from MOVETO client Javascript!");
};

module.exports = moveTo;

test.js

var test = {};

console.log("test.js loaded...");

test.logHelloWorld = function(){
  console.log("Hello World logHelloWorld() from TEST client Javascript!");
};

module.exports = test;

moveTo.handlebars

moveTo
<script type="text/javascript">
  window.onload = function(){
    console.log("ON LOAD...");
    t3toolbox.main.moveTo.logHelloWorld();
    t3toolbox.main.test.logHelloWorld();
  }
</script>

As you can see you still have to use the main after t3toolbox. I never accomplished the configuration where you end up with

var mylibrary = {
  moveTO: {/*...*/},
  test: {/*...*/}
}

It always end up with:

var mylibrary = {
  main: {
    moveTo: {/*...*/},
    test: {/*...*/}
  }
}

Upvotes: 0

Views: 280

Answers (1)

hazardous
hazardous

Reputation: 10837

Try adding library to output configuration, like so -

var webpack = require('webpack');
var path = require('path');

module.exports = {
  entry: ['./public/js/common.js', './public/js/moveTo.js'],
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'bundle.min.js',
    library: 'moveTo'
  },
  plugins: process.env.NODE_ENV === 'production' ? [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.UglifyJsPlugin()
  ] : []
}

If your library has several exported entities, use this -

var webpack = require('webpack');
var path = require('path');

module.exports = {
  entry: ['./public/js/common.js', './public/js/moveTo.js'],
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'bundle.min.js',
    library: ["mylibrary", "[name]"]
  },
  plugins: process.env.NODE_ENV === 'production' ? [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.UglifyJsPlugin()
  ] : []
}

This example is based on https://github.com/webpack/webpack/blob/master/examples/multi-part-library/webpack.config.js#L10.

This example configuration will create an export of this form:

var mylibrary : {
    "common": {/* exports from common */},
    "moveTo": {/* exports from moveTo */}
}

So you can use them in your code using mylibrary.common, mylibrary.moveTo etc.

If you don't want to club all of your imports in "mylibrary", you can change the library to -

library:"[name]"

This will create separate var moveTo = ... and var test = ... exports.

Upvotes: 1

Related Questions