Search code examples
webpackwebpack-2

Webpack 2 refusing to ignore lovell/sharp in node_modules folder


I am trying to create an app in Electron which uses React, Webpack 2 Sharp and Electron.

I just added Sharp (https://github.com/lovell/sharp) and Webpack is adamantly trying to build Sharp but I don't think it should be (I could be wrong and if so, how would I get these files to load)?

I get the following stdout:

WARNING in ./~/sharp/lib/constructor.js
Module not found: Error: Can't resolve '../vendor/lib/versions.json' in '/Users/andy/Development/image-browser/node_modules/sharp/lib'
@ ./~/sharp/lib/constructor.js 23:15-53
@ ./~/sharp/lib/index.js
@ ./app/src/utils/getImage.js
@ ./app/src/components/Images/image.js
@ ./app/src/components/Images/index.js
@ ./app/src/App.js
@ ./app/src/entry.js

WARNING in ./~/sharp/lib/icc/sRGB.icc
Module parse failed: /Users/andy/Development/image-browser/node_modules/sharp/lib/icc/sRGB.icc Unexpected character '' (1:0)
You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)
@ ./~/sharp/lib ^\.\/.*$
@ ./~/sharp/lib/index.js
@ ./app/src/utils/getImage.js
@ ./app/src/components/Images/image.js
@ ./app/src/components/Images/index.js
@ ./app/src/App.js
@ ./app/src/entry.js

WARNING in ./~/sharp/lib/icc/cmyk.icm
Module parse failed: /Users/andy/Development/image-browser/node_modules/sharp/lib/icc/cmyk.icm Unexpected character '' (1:0)
You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)
@ ./~/sharp/lib ^\.\/.*$
@ ./~/sharp/lib/index.js
@ ./app/src/utils/getImage.js
@ ./app/src/components/Images/image.js
@ ./app/src/components/Images/index.js
@ ./app/src/App.js
@ ./app/src/entry.js

ERROR in ./~/sharp/build/Release/sharp.node
Module parse failed: /Users/andy/Development/image-browser/node_modules/sharp/build/Release/sharp.node Unexpected character '�' (1:0)
You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)
@ ./~/sharp/lib/constructor.js 8:14-52
@ ./~/sharp/lib/index.js
@ ./app/src/utils/getImage.js
@ ./app/src/components/Images/image.js
@ ./app/src/components/Images/index.js
@ ./app/src/App.js
@ ./app/src/entry.js

webpack.config.js

const ExtractTextPlugin = require('extract-text-webpack-plugin')

module.exports = {

    watch: true,

    target: 'electron',

    entry: './app/src/entry.js',

    devtool: 'source-map',

    output: {
        path: __dirname + '/app/build',
        publicPath: 'build/',
        filename: 'bundle.js'
    },

    module: {
        rules: [
            {
                test: /\.js$/,
                include: /\/app\/src/,
                // exclude: /(node_modules)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: [
                            'env',
                            'react'
                        ]
                    }
                }
            },
            // {
            //     test: /\.node$/,
            //     use: {
            //         loader: 'node-loader'
            //     }
            // },
            {
                test: /\.(sass|scss)$/,
                include: /\/app\/src/,
                // exclude: /(node_modules)/,
                use: [
                    'style-loader',
                    'css-loader',
                    'sass-loader',
                ]
            },
            {
                test: /\.(png|jpg|gif|svg)$/,
                include: /\/app\/src/,
                // exclude: /(node_modules)/,
                use: {
                    loader: 'file-loader',
                    query: {
                        name: '[name].[ext]?[hash]'
                    }
                }
            }
        ]
    },

    plugins: [
        new ExtractTextPlugin({
            filename: 'bundle.css',
            disable: false,
            allChunks: true
        })
    ]
}

My babel config (extracted from package.json):

"babel": {
    "retainLines": true,
    "presets": [
        [
            "env",
            {
            "targets": {
                "electron": 1.6,
                "node": 7.9
            },
                "modules": false,
                "debug": true
            }
        ],
        "es2015",
        "es2016",
        "es2017"
    ]
},

Any ideas?


Solution

  • I have successfully got this working and the following is a mirror of the comment I added to this Github issue: https://github.com/lovell/sharp/issues/794

    The key was finding this article: http://jlongster.com/Backend-Apps-with-Webpack--Part-I#p28 (thanks @jlongster).

    My webpack.config.js looks like the following:

    const ExtractTextPlugin = require('extract-text-webpack-plugin')
    const path = require('path');
    const fs = require('fs');
    
    // FROM: http://jlongster.com/Backend-Apps-with-Webpack--Part-I#p28
    const nodeModules = {};
    fs.readdirSync('node_modules')
        .filter(item => ['.bin'].indexOf(item) === -1)  // exclude the .bin folder
        .forEach((mod) => {
            nodeModules[mod] = 'commonjs ' + mod;
        });
    
    module.exports = {
        watch: true,
        target: 'electron',
        entry: ['babel-polyfill', './app/src/entry.js'],
        devtool: 'source-map',
        externals: nodeModules,
        output: {
            path: __dirname + '/app/build',
            publicPath: 'build/',
            filename: 'bundle.js'
        },
        module: {
            rules: [
                {
                    test: /\.js$/,
                    include: path.resolve(__dirname, 'app/src'),
                    use: {
                        loader: 'babel-loader',
                        options: {
                            presets: [
                                'env',
                                'react'
                            ]
                        }
                    }
                },
                {
                    test: /\.(sass|scss)$/,
                    include: path.resolve(__dirname, 'app/src'),
                    use: [
                        'style-loader',
                        'css-loader',
                        'sass-loader',
                    ]
                },
                {
                    test: /\.(png|jpg|gif|svg)$/,
                    include: path.resolve(__dirname, 'app/src'),
                    use: {
                        loader: 'file-loader',
                        query: {
                            name: '[name].[ext]?[hash]'
                        }
                    }
                }
            ]
        },
        plugins: [
            new ExtractTextPlugin({
                filename: 'bundle.css',
                disable: false,
                allChunks: true
            })
        ]
    }
    

    TL;DR

    Use this to get a list of ALL your node modules:

    const nodeModules = {};
    fs.readdirSync('node_modules')
        .filter(item => ['.bin'].indexOf(item) === -1 )  // exclude the .bin folder
        .forEach((mod) => {
            nodeModules[mod] = 'commonjs ' + mod;
        });
    

    and hand the nodeModules variable to Webpack's externals key:

    externals: nodeModules,
    

    Alternatively, you could use one of the Ignore Module Webpack plugins but I have not tried that myself.