<p dir="auto"><strong>Do you want to request a <em>feature</em> or report a <em>bug</em>?</strong><br>
BUG : <a href="https://stackoverflow.com/questions/48695579/how-to-remove-eval-and-function-constructor-from-webpack-build-to-avoid-csp-issu" rel="nofollow">Stackoverflow Link</a></p>


<p dir="auto"><strong>What is the current behavior?</strong><br>
It gives both eval and Function contructor which is not required</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="try {
    // This works if eval is allowed (see CSP)
    g = g || Function(&quot;return this&quot;)() || (1,eval)(&quot;this&quot;);
} catch(e) {
    // This works if the window reference is available
    if(typeof window === &quot;object&quot;)
        g = window;
}

// Another method of build 
function setImmediate(callback) {
      // Callback can either be a function or a string
      if (typeof callback !== &quot;function&quot;) {
        callback = new Function(&quot;&quot; + callback);
      }"><pre class="notranslate"><code class="notranslate">try {
    // This works if eval is allowed (see CSP)
    g = g || Function("return this")() || (1,eval)("this");
} catch(e) {
    // This works if the window reference is available
    if(typeof window === "object")
        g = window;
}

// Another method of build 
function setImmediate(callback) {
      // Callback can either be a function or a string
      if (typeof callback !== "function") {
        callback = new Function("" + callback);
      }
</code></pre></div>
<p dir="auto"><strong>If the current behavior is a bug, please provide the steps to reproduce.</strong></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$ npm install -g vue-cli
$ vue init webpack-simple my-project
$ cd my-project
$ npm install
$ npm run prod

You can see in `build.js` having eval "><pre class="notranslate"><code class="notranslate">$ npm install -g vue-cli
$ vue init webpack-simple my-project
$ cd my-project
$ npm install
$ npm run prod

You can see in `build.js` having eval 
</code></pre></div>
<p dir="auto"><strong>What is the expected behavior?</strong><br>
I expect that webpack should provide provision to build according to CSP policy as I am using runtime vue which does not even require compiler.</p>
<p dir="auto"><strong>Please mention other relevant information such as the browser version, Node.js version, webpack version and Operating System.</strong></p>
<p dir="auto">Node.js : 9.5.0</p>
<p dir="auto">Tried it with latest config too.<br>
<strong>Package.json</strong></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="{
  &quot;webpack&quot;: &quot;^3.10.0&quot;,
  &quot;babel-core&quot;: &quot;^6.18.2&quot;,
  &quot;babel-loader&quot;: &quot;^7.1.2&quot;,
  &quot;babel-preset-es2015&quot;: &quot;^6.18.0&quot;,
  &quot;babel-preset-stage-2&quot;: &quot;^6.24.1&quot;,
  &quot;file-loader&quot;: &quot;^0.9.0&quot;,
  &quot;style-loader&quot;: &quot;^0.18.2&quot;,
  &quot;vue-loader&quot;: &quot;^10.0.2&quot;
}"><pre class="notranslate"><code class="notranslate">{
  "webpack": "^3.10.0",
  "babel-core": "^6.18.2",
  "babel-loader": "^7.1.2",
  "babel-preset-es2015": "^6.18.0",
  "babel-preset-stage-2": "^6.24.1",
  "file-loader": "^0.9.0",
  "style-loader": "^0.18.2",
  "vue-loader": "^10.0.2"
}
</code></pre></div>
<p dir="auto">I am currently migrating webpack.config.js from webpack 3 to webpack 4.</p>
<p dir="auto">The application uses the style-loader useable feature to load themes as follows:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="loader = require('../styles/app.theme.' + theme + '.less');
loader(function (style) {
    style.use();
});"><pre class="notranslate"><code class="notranslate">loader = require('../styles/app.theme.' + theme + '.less');
loader(function (style) {
    style.use();
});
</code></pre></div>
<p dir="auto">It also uses the bundle-loader to load cultures as follows:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="var loader = require('bundle-loader?name=[name]!./cultures/app.culture.' + locale + '.js');
loader(setLocale);"><pre class="notranslate"><code class="notranslate">var loader = require('bundle-loader?name=[name]!./cultures/app.culture.' + locale + '.js');
loader(setLocale);
</code></pre></div>
<p dir="auto">My webpack 3 configuration is:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="var path = require('path');
var util = require('util');
var webpack = require('webpack');
var config = require('./webapp/config');
var pkg = require('./package.json');
var environment = config.environment || 'development';

console.log('webpack environment is ' + environment);
console.log('webpack public path is ' + config.get('uris:webpack:root'));
console.log('building version ' + pkg.version);

/**
 * DefinePlugin
 */
var definePlugin = new webpack.DefinePlugin({
    __NODE_ENV__: JSON.stringify(environment),
    __VERSION__: JSON.stringify(pkg.version)
});

/**
 * CommonsChunkPlugin
 */
var commonsChunkPlugin =
    new webpack.optimize.CommonsChunkPlugin({ name: 'common', filename: 'common.bundle.js', chunks: ['error', 'home', 'post', 'page', 'search'] });

/**
 * Webpack configuration
 */
module.exports = {
    context: path.join(__dirname, '/'),
    devtool: 'source-map',
    entry: {
        // We need init especially because of FOUJI
        init:   './js/app.init.js',
        // One entry per view
        error:  './js/app.error.js',
        home:   './js/app.home.js',
        page:   './js/app.page.js',
        post:   './js/app.post.js',
        search: './js/app.search.js'
    },
    externals: { // CDN modules
        jquery: 'jQuery'
    },
    output: {
        path: path.join(__dirname, '/webapp/public/build'),
        publicPath: config.get('uris:webpack:root'),
        filename: '[name].bundle.js?v=' + pkg.version,
        chunkFilename: '[name].chunk.js?v=' + pkg.version
    },
    resolve: {
        modules: [
            path.resolve('.'),
            path.resolve('./js/vendor/kendo'),
            'node_modules'
        ]
    },
    module: {
        rules: [
            {
                test: /\.jsx/, // see ./web_modules/jsx-loader
                use: [
                    { loader: './web_modules/jsx-loader', options: { config: 'webapp/config' } }
                ]
            },
            {
                test: /app\.theme\.[a-z0-9]+\.less$/,
                use: [
                    { loader: 'bundle-loader?name=[name]' },
                    { loader: 'style-loader/useable' },
                    { loader: 'css-loader', options: { importLoaders: 2 } },
                    { loader: 'postcss-loader' },
                    { loader: 'less-loader', options: { compress: true, relativeUrls: true, strictMath: true } }
                ]
            },
            {
                test: /\.less$/,
                exclude: /app\.theme\.[a-z0-9]+\.less$/,
                use: [
                    { loader: 'style-loader' },
                    { loader: 'css-loader', options: { importLoaders: 1 } },
                    { loader: 'postcss-loader' },
                    { loader: 'less-loader', options: { compress: true, relativeUrls: true, strictMath: true } }
                ]
            },
            {
                test: /\.css$/,
                use: [
                    { loader: 'style-loader' },
                    { loader: 'css-loader', options: { importLoaders: 1 } },
                    { loader: 'postcss-loader' }
                ]
            },
            {
                test: /\.(gif|png|jpe?g)$/,
                use: [
                    { loader: 'url-loader', options: { limit: 8192 } }
                ]
            },
            {
                test: /\.woff(2)?/,
                use: [
                    { loader: 'url-loader', options: { limit: 10000, mimetype: 'application/font-woff' } }
                ]
            },
            {
                test: /\.(ttf|eot|svg)/,
                use: [
                    { loader: 'file-loader' }
                ]
            }
        ]
    },
    plugins: [
        definePlugin,
        commonsChunkPlugin
    ]
};"><pre class="notranslate"><code class="notranslate">var path = require('path');
var util = require('util');
var webpack = require('webpack');
var config = require('./webapp/config');
var pkg = require('./package.json');
var environment = config.environment || 'development';

console.log('webpack environment is ' + environment);
console.log('webpack public path is ' + config.get('uris:webpack:root'));
console.log('building version ' + pkg.version);

/**
 * DefinePlugin
 */
var definePlugin = new webpack.DefinePlugin({
    __NODE_ENV__: JSON.stringify(environment),
    __VERSION__: JSON.stringify(pkg.version)
});

/**
 * CommonsChunkPlugin
 */
var commonsChunkPlugin =
    new webpack.optimize.CommonsChunkPlugin({ name: 'common', filename: 'common.bundle.js', chunks: ['error', 'home', 'post', 'page', 'search'] });

/**
 * Webpack configuration
 */
module.exports = {
    context: path.join(__dirname, '/'),
    devtool: 'source-map',
    entry: {
        // We need init especially because of FOUJI
        init:   './js/app.init.js',
        // One entry per view
        error:  './js/app.error.js',
        home:   './js/app.home.js',
        page:   './js/app.page.js',
        post:   './js/app.post.js',
        search: './js/app.search.js'
    },
    externals: { // CDN modules
        jquery: 'jQuery'
    },
    output: {
        path: path.join(__dirname, '/webapp/public/build'),
        publicPath: config.get('uris:webpack:root'),
        filename: '[name].bundle.js?v=' + pkg.version,
        chunkFilename: '[name].chunk.js?v=' + pkg.version
    },
    resolve: {
        modules: [
            path.resolve('.'),
            path.resolve('./js/vendor/kendo'),
            'node_modules'
        ]
    },
    module: {
        rules: [
            {
                test: /\.jsx/, // see ./web_modules/jsx-loader
                use: [
                    { loader: './web_modules/jsx-loader', options: { config: 'webapp/config' } }
                ]
            },
            {
                test: /app\.theme\.[a-z0-9]+\.less$/,
                use: [
                    { loader: 'bundle-loader?name=[name]' },
                    { loader: 'style-loader/useable' },
                    { loader: 'css-loader', options: { importLoaders: 2 } },
                    { loader: 'postcss-loader' },
                    { loader: 'less-loader', options: { compress: true, relativeUrls: true, strictMath: true } }
                ]
            },
            {
                test: /\.less$/,
                exclude: /app\.theme\.[a-z0-9]+\.less$/,
                use: [
                    { loader: 'style-loader' },
                    { loader: 'css-loader', options: { importLoaders: 1 } },
                    { loader: 'postcss-loader' },
                    { loader: 'less-loader', options: { compress: true, relativeUrls: true, strictMath: true } }
                ]
            },
            {
                test: /\.css$/,
                use: [
                    { loader: 'style-loader' },
                    { loader: 'css-loader', options: { importLoaders: 1 } },
                    { loader: 'postcss-loader' }
                ]
            },
            {
                test: /\.(gif|png|jpe?g)$/,
                use: [
                    { loader: 'url-loader', options: { limit: 8192 } }
                ]
            },
            {
                test: /\.woff(2)?/,
                use: [
                    { loader: 'url-loader', options: { limit: 10000, mimetype: 'application/font-woff' } }
                ]
            },
            {
                test: /\.(ttf|eot|svg)/,
                use: [
                    { loader: 'file-loader' }
                ]
            }
        ]
    },
    plugins: [
        definePlugin,
        commonsChunkPlugin
    ]
};
</code></pre></div>
<p dir="auto">It produces:</p>
<ul dir="auto">
<li>a chunk for each culture</li>
<li>a chunk for each theme</li>
<li>a bundle for each page (entry point)</li>
<li>a common bundle for all code that is common to all entry points.</li>
</ul>
<p dir="auto">In order to migrate this to webpack 4, I have removed:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="var commonsChunkPlugin =
    new webpack.optimize.CommonsChunkPlugin({ name: 'common', filename: 'common.bundle.js', chunks: ['error', 'home', 'post', 'page', 'search'] });"><pre class="notranslate"><code class="notranslate">var commonsChunkPlugin =
    new webpack.optimize.CommonsChunkPlugin({ name: 'common', filename: 'common.bundle.js', chunks: ['error', 'home', 'post', 'page', 'search'] });
</code></pre></div>
<p dir="auto">And I have added the following optimization section:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="optimization: {
    minimize: true,
    splitChunks: { // https://gist.github.com/sokra/1522d586b8e5c0f5072d7565c2bee693
        cacheGroups: {
            common: {
                chunks: 'initial',
                // enforce: true,
                filename: '[name].bundle.js?v=' + pkg.version,
                name: 'common',
                test: /[\\/]js[\\/]/
                // reuseExistingChunk: true
            }
        }
    }
},"><pre class="notranslate"><code class="notranslate">optimization: {
    minimize: true,
    splitChunks: { // https://gist.github.com/sokra/1522d586b8e5c0f5072d7565c2bee693
        cacheGroups: {
            common: {
                chunks: 'initial',
                // enforce: true,
                filename: '[name].bundle.js?v=' + pkg.version,
                name: 'common',
                test: /[\\/]js[\\/]/
                // reuseExistingChunk: true
            }
        }
    }
},
</code></pre></div>
<p dir="auto">As a result, I get with webpack 4 the same list of files as produced with webpack 3, except webpack 4 does not detect that chunks have been produced for themes loaded with the style-loader <strong>useable</strong> feature and embeds all themes (for which it produces chunks) into each entry bundle. As a result themes are duplicated in their own dedicated chunks and in each entry bundle, resulting in much bigger entry bundles.</p>
<p dir="auto">Note: enforce and reuseExistingChunk do not affect the output.</p>
<p dir="auto"><strong>Is this a bug or a configuration issue?</strong></p>
<p dir="auto">Should you feel the need to experiment, the two following projects have very similar webpack configs:</p>
<ul dir="auto">
<li><a href="https://github.com/kidoju/Kidoju-Blog">https://github.com/kidoju/Kidoju-Blog</a> (expressJS)</li>
<li><a href="https://github.com/kidoju/Kidoju-Mobile">https://github.com/kidoju/Kidoju-Mobile</a> (phonegap)</li>
</ul>