Search code examples
javascripttwitter-bootstrapnpmwebpackwebpack-2

What does importing a module actually do in the context of webpack?


I am learning webpack, coming from an amateur use of JavaScript in pure browser mode. I will use bootstrap and moment as examples for highlighting the confusing points.

In pure browser mode, I am addding both CSS and JS components at the bottom of my <body> (I removed the full paths or URLs for clarity):

(...)
    <script src="bootstrap.js"></script>
    <link href="botstrap.css">
    <script src="moment.js"></script>
    <script src="myownscript.js"></script>
</body>
</html>

When running the app

  • the Bootstrap components are loaded (the CSS I use directly in <div class='some bootstrap class'>, and the JS which is needed by Bootstrap but which I do not use directly),

  • as well as moment.js which exposes moment I can use in myownscript.js (moment.now() for instance)

I then discovered webpack which is great but I fail to understand how to use the modules I import in my entry.js code.

Specifically:

For bootstrap I initially tried (after installing it with npm)

import 'bootstrap'

This did not enabled me to use the CSS I normally use in my code, the code looks like there is no Bootstrap applied.

I then tried

import 'bootstrap/dist/css/bootstrap.css'

and, behold, Bootstrap is applied. Except for the Javascript part.

Subquestion: should I just import 'bootstrap/dist/js/bootstrap.js' and it will be used in the same way as with the pure browser experience?

I doubt so because...

For moment: I initially tried to just

import 'moment'

But that was not enough. I needed to

import 'moment'
Window.moment = moment

to expose moment to be used as, say, moment.now() in my scripts.

My question: is import '<module>' in any way magical or should I just treat the modules installed via npm and residing in node_modules as a plain repository and import them manually?

If so: what is the purpose of a bare import '<module>'?


Solution

  • What is available through the import <module> depends on what is exposed by the module package.json main entry.

    For bootstrap, this is dist/js/bootstrap.js. But this file does not export anything, and import 'bootstrap' will load all of Bootstrap's jQuery plugins onto the jQuery object. Also you have to import 'bootstrap/dist/css/bootstrap.css' manually.

    Here is a minimal webpack setup to make this work.

    package.json

    {
      "name": "test",
      "devDependencies": {
        "bootstrap": "^3.3.7",
        "css-loader": "^0.28.4",
        "file-loader": "^0.11.2",
        "jquery": "^3.2.1",
        "moment": "^2.18.1",
        "style-loader": "^0.18.2",
        "webpack": "^3.4.1"
      }
    }
    

    webpack.config.js

    const path = require('path')
    const webpack = require('webpack')
    
    module.exports = {
      entry: "./scripts.js",
      output: {
        path: path.resolve(__dirname, ""),
        filename: "bundle.js"
      },
      module: {
        rules: [{
          test: /\.css$/,
          use: [
            { loader: "style-loader" },
            { loader: "css-loader" }
          ]
        },
        {
          test: /\.(eot|svg|ttf|woff|woff2)$/,
          use: 'file-loader?name=public/fonts/[name].[ext]'
        }]
      },
      plugins: [
        new webpack.ProvidePlugin({
         $: 'jquery',
         jQuery: 'jquery'
        })
      ]
    }
    

    index.html

    <!DOCTYPE html>
    <html>
    <head>
      <title>test</title>
    </head>
    <body>
     <h1>Test</h1>
     <div id="myModal">myModal</div>
    <script src="bundle.js"></script>
    </body>
    </html>
    

    and scripts.js

    import 'bootstrap'
    import moment from 'moment'
    import 'bootstrap/dist/css/bootstrap.css'
    
    console.log(moment.now(), $('#myModal').modal(), jQuery)
    

    jQuery is loaded globally via the webpack Provide plugin and Bootstrap's javascript is attached to the jQuery object.

    And from the command line:

    $ npm install 
    $ webpack