Matthias
Matthias

Reputation: 2775

Webpack does not import bundles from node_modules (js only)

Good Morning,

I'm quite new to Webpack and feel a bit lost - importing modules from the source path works just fine - but importing modules from node_modules (e.g. jQuery) gives me error messages that the module is not found. I am completely lost and don't even know what to look for or how to debug this further.

The error message i am getting is:

external "jquery":1 Uncaught ReferenceError: jquery is not defined
    at Object.jquery (external "jquery":1)
    at __webpack_require__ (bootstrap:723)
    at fn (bootstrap:100)
    at Object../js/ManagementApplication.ts (ManagementApplication.ts:5)
    at __webpack_require__ (bootstrap:723)
    at fn (bootstrap:100)
    at Object.0 (dist.js:40457)
    at __webpack_require__ (bootstrap:723)
    at bootstrap:790
    at bootstrap:790
jquery @ external "jquery":1
__webpack_require__ @ bootstrap:723
fn @ bootstrap:100
./js/ManagementApplication.ts @ ManagementApplication.ts:5
__webpack_require__ @ bootstrap:723
fn @ bootstrap:100
0 @ dist.js:40457
__webpack_require__ @ bootstrap:723
(anonymous) @ bootstrap:790
(anonymous) @ bootstrap:790

and here is my webpack config:

// shared config (dev and prod)
const {resolve} = require('path');
const {CheckerPlugin} = require('awesome-typescript-loader');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require("webpack")


module.exports = {
    resolve: {
        extensions: ['.ts', '.js'],
    },
    context: resolve(__dirname, '../src/main/'),
    output: {
        filename: "dist.js",
        path: resolve(__dirname, '../target')
    },
    externals: {
        bootstrap: "bootstrap",
        jquery: "jquery"
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                use: ['babel-loader'],
            },
            {
                test: /\.tsx?$/,
                use: ['babel-loader', 'awesome-typescript-loader'],
            },
            {
                test: /\.css$/,
                use: ['style-loader', {loader: 'css-loader', options: {importLoaders: 1}}],
            },
            {
                test: /\.(scss)$/,
                use: [{
                    loader: 'style-loader', // inject CSS to page
                }, {
                    loader: 'css-loader', // translates CSS into CommonJS modules
                }, {
                    loader: 'postcss-loader', // Run postcss actions
                    options: {
                        plugins: function () { // postcss plugins, can be exported to postcss.config.js
                            return [
                                require('autoprefixer')
                            ];
                        }
                    }
                }, {
                    loader: 'sass-loader' // compiles Sass to CSS
                }]
            },

            {
                test: /\.woff2?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
                use: 'url-loader?limit=10000',
            },
            {
                test: /\.hbs/,
                loaders: "handlebars-loader"
            },
            {
                test: /\.(jpe?g|png|gif|svg)$/i,
                loaders: [
                    'file-loader?hash=sha512&digest=hex&name=img/[hash].[ext]',
                    'image-webpack-loader?bypassOnDebug&optipng.optimizationLevel=7&gifsicle.interlaced=false',
                ],
            },
        ],
    },
    plugins: [
        new CheckerPlugin(),
        new HtmlWebpackPlugin(),
        new webpack.IgnorePlugin(/\/iconv-loader$/)
    ],
    performance: {
        hints: false,
    },
};

and this one:

// development config
const merge = require('webpack-merge');
const webpack = require('webpack');
const commonConfig = require('./common');

module.exports = merge(commonConfig, {
    mode: 'development',
    entry: [
        'webpack-dev-server/client?http://localhost:4000',// bundle the client for webpack-dev-server and connect to the provided endpoint
        'webpack/hot/only-dev-server', // bundle the client for hot reloading, only- means to only hot reload for successful updates
        './js/ManagementApplication.ts' // the entry point of our app
    ],

    devServer: {
        hot: true,
        host: "0.0.0.0",
        port: "4000"

    },
    devtool: 'source-map',
    plugins: [
        new webpack.HotModuleReplacementPlugin(), // enable HMR globally
        new webpack.NamedModulesPlugin(), // prints more readable module names in the browser console on HMR updates
    ],
});

(both of them are loaded, the latter one overriding the first one).

I've checked a billion times that the libraries are correctly inside node_modules - just don't know why they are not loaded. This problem is not specific only to a specific library but genreally to all libraries.

Importing css resources from libraries works fine in contrast.

Does anyone have an idea how to fix this or can help me understanding what is happening?

Upvotes: 2

Views: 4271

Answers (2)

Derek Nguyen
Derek Nguyen

Reputation: 11577

If you intended jquery to be treated as an external, @Pandelis answer's right (note the uppercase Q: jquery: jQuery). But in case you want to import jquery as a node module, see below.

Use jQuery as a node module

If you want to use jQuery as a node module & have it bundled, you should install jquery from npm

npm install jquery

Then import it in your code

import $ from "jquery";

No need to add anything to webpack.config.js. But if you want to use jQuery as an external:

Use jQuery as an external

When you do something like this in webpack.config.js:

...
module.exports = {
  externals: {
    jquery: "jQuery" // or jquery: "$"
  },
  ...
}

It tells webpack that in the line import jquery, jquery shouldn't be bundled; instead, look for the jQuery object in the global scope (which is window in our case). Both jQuery and $ will be valid. It also means you have to load jquery from external source:

#index.html

<script
  src="https://code.jquery.com/jquery-3.3.1.min.js"
  integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
  crossorigin="anonymous"></script>
<sript src="bundle.js"></script>

Then in your code, you can then do

import 'jquery' // or import $ from 'jquery'
$...

Just to illustrate, you can also do externals: { foo: 'jQuery' } and import 'foo' would still work.

Hope it helps!

Upvotes: 1

Pandelis
Pandelis

Reputation: 1968

Not actually 100% sure without looking at more of the project but give this a go.

Set your jquery external to:

"jquery": "jQuery"

and use jquery in your project as: import jQuery from 'jquery' or import $ from 'jquery'

Upvotes: 0

Related Questions