Coder Social home page Coder Social logo

webpack-common-shake's Introduction

CommonJS Tree Shaker plugin for Webpack

NPM version Build Status

Fancy shaking logo

Please file an issue if anything is broken.

See common-shake for abstract bundler-independent implementation.

NOTE: webpack version 4 may be needed in order to run this. If you're using webpack 3, please use [email protected].

NOTE: Logo is a modified version of webpack's logo

Why?

There are vast amount of CommonJS modules out there. Thus CommonJS Tree Shaking is as important as the ESM module import/export shaking.

How?

This plugin removes unused assignments to exports properties leaving removal of the (presumably) dead code to UglifyJS. If, for example, you had a module:

exports.used = 1;
var tmp = exports.unused = 2;

This plugin will transform it to:

exports.used = 1;
var tmp = 2;

It is up to UglifyJS (or some other optimizer) to decide, whether tmp is used or not and delete it. Luckily it is much simpler for it to do if the uses are not clouded by exporting the values.

Usage

Example webpack.config.js:

const ShakePlugin = require('webpack-common-shake').Plugin;

module.exports = [{
  entry: 'entry.js'
  output: {
    path: 'dist',
    filename: 'output.js'
  },
  plugins: [ new ShakePlugin() ]
}];

Demonstration

See webpack-common-shake-demo for size comparison of output with and without this plugin.

Options

Plugin constructor accepts options object which may have following properties:

const plugin = new ShakePlugin({
  warnings: {
    global: true,
    module: false
  } /* default */,

  // Invoked on every deleted unused property
  onExportDelete: (resource, property) => {},

  // See `Limitations` section for description
  onModuleBailout: (module, bailouts) => { ... },
  onGlobalBailout: (bailouts) => { ... }
});

Limitations

Although, generally this module works and helps removing unused code from the bundles. There are some limitations that may prevent it from running either partially or completely. Some examples are provided below, otherwise please use common sense (or onModuleBailout, onGlobalBailout plugin options).

Some local (partial) bailouts:

  • Dynamic exports exports[Math.random()] = ...
  • Overriding imported vars var a = require('./a'); a.lib; a = require('./b')
  • Using require in unknown way console.log(require('./lib'))
  • Destructuring require dynamically { [prop]: name } = require('./a')
  • Dynamic import var fn = require('./lib')[Math.random()]

Some global (full) bailouts:

  • Dynamic use of require require(Math.random())

This plugin will print some webpack warnings. In any case, bailouts may be obtained programmatically too:

const plugin = new ShakePlugin({
  onModuleBailout: (module, bailouts) => { ... },
  onGlobalBailout: (bailouts) => { ... }
});

Graph

For debugging and inspection purposes a graph in dot format may be obtained using onGraph option:

const plugin = new ShakePlugin({
  onGraph: (graph) => { ... }
});

LICENSE

This software is licensed under the MIT License.

Copyright Fedor Indutny, 2017.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

webpack-common-shake's People

Contributors

dependabot[bot] avatar indutny avatar jkrems avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

webpack-common-shake's Issues

HookWebpackError: Cannot read properties of undefined (reading 'forEach')

Hi, I get the following error when running with these versions:

Package versions

│ ├── [email protected]
│ └── [email protected]

Error

  common-shake:module use this="../ZodError" property="ZodIssueCode" from="/home/user/project/node_modules/zod/lib/locales/en.js" recursive=false +0ms
  common-shake:module use this="../ZodError" property="ZodIssueCode" from="/home/user/project/node_modules/zod/lib/locales/en.js" recursive=false +1ms
  common-shake:module use this="../helpers/util" property="util" from="/home/user/project/node_modules/zod/lib/locales/en.js" recursive=false +0ms
[webpack-cli] HookWebpackError: Cannot read properties of undefined (reading 'forEach')
    at makeWebpackError (/home/user/project/node_modules/webpack/lib/HookWebpackError.js:48:9)
    at /home/user/project/node_modules/webpack/lib/Compilation.js:2974:8
    at Hook.eval [as callAsync] (eval at create (/home/user/project/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:12:1)
    at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (/home/user/project/node_modules/tapable/lib/Hook.js:18:14)
    at /home/user/project/node_modules/webpack/lib/Compilation.js:2968:36
    at eval (eval at create (/home/user/project/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:11:1)
    at /home/user/project/node_modules/html-webpack-plugin/lib/cached-child-compiler.js:237:53
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
-- inner error --
TypeError: Cannot read properties of undefined (reading 'forEach')
    at /home/user/project/node_modules/webpack-common-shake/lib/shake/plugin.js:79:24
    at Set.forEach (<anonymous>)
    at /home/user/project/node_modules/webpack-common-shake/lib/shake/plugin.js:78:15
    at Hook.eval [as callAsync] (eval at create (/home/user/project/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:9:16)
    at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (/home/user/project/node_modules/tapable/lib/Hook.js:18:14)
    at /home/user/project/node_modules/webpack/lib/Compilation.js:2968:36
    at eval (eval at create (/home/user/project/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:11:1)
    at /home/user/project/node_modules/html-webpack-plugin/lib/cached-child-compiler.js:237:53
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
caused by plugins in Compilation.hooks.optimizeChunkModules
TypeError: Cannot read properties of undefined (reading 'forEach')
    at /home/user/project/node_modules/webpack-common-shake/lib/shake/plugin.js:79:24
    at Set.forEach (<anonymous>)
    at /home/user/project/node_modules/webpack-common-shake/lib/shake/plugin.js:78:15
    at Hook.eval [as callAsync] (eval at create (/home/user/project/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:9:16)
    at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (/home/user/project/node_modules/tapable/lib/Hook.js:18:14)
    at /home/user/project/node_modules/webpack/lib/Compilation.js:2968:36
    at eval (eval at create (/home/user/project/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:11:1)
    at /home/user/project/node_modules/html-webpack-plugin/lib/cached-child-compiler.js:237:53
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
const CompressionPlugin = require('compression-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const webpack = require('webpack')
const TerserPlugin = require('terser-webpack-plugin')
const path = require('path')
const { JsonAccessOptimizer } = require('webpack-json-access-optimizer')
const { ProvidePlugin } = require('webpack')
const ShakePlugin = require('webpack-common-shake').Plugin

module.exports = (env, argv) => {
    const isProduction = argv.mode === 'production'

    return {
        entry: './src/index.tsx',
        output: {
            filename: '[name].bundle.js',
            path: path.resolve(__dirname, 'dist'),
        },
        module: {
            rules: [
                {
                    include: /node_modules/,
                    test: /\.css$/,
                    sideEffects: true,
                    use: [
                        MiniCssExtractPlugin.loader,
                        {
                            loader: require.resolve('css-loader'),
                            options: {
                                url: false,
                            },
                        },
                    ],
                },
                {
                    exclude: /(node_modules)/,
                    test: /\.(ts|tsx)$/,
                    use: [
                        {
                            loader: require.resolve('ts-loader'),
                            options: {
                                configFile: 'tsconfig.webpack.json',
                                transpileOnly: true,
                            },
                        },
                    ],
                },
                {
                    test: /locale\.json$/, // match JSON files to optimize
                    loader: 'webpack-json-access-optimizer',
                },
            ],
        },
        resolve: {
            extensions: ['.js', '.jsx', '.ts', '.tsx'],
        },
        plugins: [
            new HtmlWebpackPlugin({
                template: './src/index.html',
            }),
            new BundleAnalyzerPlugin(),
            new webpack.DefinePlugin({
                'process.env.NODE_ENV': JSON.stringify(isProduction ? 'production' : 'development'),
            }),
            // new webpack.optimize.SplitChunksPlugin(),
            new CompressionPlugin(),
            new MiniCssExtractPlugin({
                filename: 'extr.[contenthash].css',
            }),
            new ProvidePlugin({
                $t: './$tProvider',
            }),
            new JsonAccessOptimizer({
                accessorFunctionName: '$t', // i18n function name
            }),
            new ShakePlugin(), // commonJS tree shaking
        ],
        devServer: {
            static: {
                directory: __dirname + '/dist',
            },
            compress: true,
            port: 9000,
        },
        optimization: {
            minimize: isProduction,
            minimizer: [
                new TerserPlugin({
                    terserOptions: {
                        compress: {
                            drop_console: true,
                        },
                    },
                }),
            ],
            usedExports: true,
        },
    }
}

Cannot read property 'resource' of undefined

I've recently attempted to implement this package into my build chain using Webpack 3.
Unfortunately, with this plugin added, my build fails at around 80%, citing the following error:

TypeError: Cannot read property 'resource' of undefined
    at ShakePlugin.mapModule (/path/to/node_modules/webpack-common-shake/lib/shake/plugin.js:71:33)

This is on MacOS with Node v6.11.0

TypeError: Cannot read property 'forEach' of undefined

error while using this plugin with webpack 5

[email protected]
[email protected]

HookWebpackError: Cannot read property 'forEach' of undefined
    at makeWebpackError (node_modules/webpack/lib/HookWebpackError.js:49:9)
    at node_modules/webpack/lib/Compilation.js:1844:8
    at Hook.eval [as callAsync] (eval at create (node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:12:1)
    at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (node_modules/webpack/node_modules/tapable/lib/Hook.js:18:14)
    at node_modules/webpack/lib/Compilation.js:1838:36
    at Hook.eval [as callAsync] (eval at create (node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (node_modules/webpack/node_modules/tapable/lib/Hook.js:18:14)
    at Compilation.seal (node_modules/webpack/lib/Compilation.js:1829:27)
    at node_modules/webpack/lib/Compiler.js:930:20
    at node_modules/webpack/lib/Compilation.js:1706:4
    at _next2 (eval at create (node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:25:1)
    at eval (eval at create (node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:52:1)
    at node_modules/webpack/lib/FlagDependencyExportsPlugin.js:289:11
    at node_modules/neo-async/async.js:2830:7
    at Object.each (node_modules/neo-async/async.js:2850:39)
    at node_modules/webpack/lib/FlagDependencyExportsPlugin.js:268:18
-- inner error --
TypeError: Cannot read property 'forEach' of undefined
    at node_modules/webpack-common-shake/lib/shake/plugin.js:79:24
    at Set.forEach (<anonymous>)
    at node_modules/webpack-common-shake/lib/shake/plugin.js:78:15
    at Hook.eval [as callAsync] (eval at create (node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:9:16)
    at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (node_modules/webpack/node_modules/tapable/lib/Hook.js:18:14)
    at node_modules/webpack/lib/Compilation.js:1838:36
    at Hook.eval [as callAsync] (eval at create (node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (node_modules/webpack/node_modules/tapable/lib/Hook.js:18:14)
    at Compilation.seal (node_modules/webpack/lib/Compilation.js:1829:27)
    at node_modules/webpack/lib/Compiler.js:930:20
    at node_modules/webpack/lib/Compilation.js:1706:4
    at _next2 (eval at create (node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:25:1)
    at eval (eval at create (node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:52:1)
    at node_modules/webpack/lib/FlagDependencyExportsPlugin.js:289:11
    at node_modules/neo-async/async.js:2830:7
    at Object.each (node_modules/neo-async/async.js:2850:39)

Full bailouts

This plugin should fully bailout (don't apply at all) if:

  • ESM module is required (because we don't know what is inside of it)
  • On dynamic require or unknown require uses (because we don't know what properties were imported)

Global deoptimization from legacy files

I have global deoptimizations caused by some legacy AMD modules. The deopt is "Dynamic use of require", even though there is no dynamic require, because the require variable was overwritten in scope. :( Seems like a bug though (shouldn't deopt when require was overwritten, no?).

Is there a way to filter certain files from being touched by this plugin?

Some of the files that causes deopt when required:

TypeError: Cannot read property 'bailouts' of undefined

Hello,

I was trying to look the effects of running this plugin on my build and got this error.

I am webpack 3.1.0.

Happy to help with any debugging else that is needed.

TypeError: Cannot read property 'bailouts' of undefined
    at Module.mergeFrom (/Users/ruka/Projects/web/node_modules/common-shake/lib/shake/module.js:106:17)
    at Analyzer.resolve (/Users/ruka/Projects/web/node_modules/common-shake/lib/shake/analyzer.js:60:12)
    at module.reasons.forEach (/Users/ruka/Projects/web/node_modules/webpack-common-shake/lib/shake/plugin.js:77:26)
    at Array.forEach (native)
    at modules.forEach (/Users/ruka/Projects/web/node_modules/webpack-common-shake/lib/shake/plugin.js:70:24)
    at Array.forEach (native)
    at Compilation.compilation.plugin (/Users/ruka/Projects/web/node_modules/webpack-common-shake/lib/shake/plugin.js:69:15)
    at Compilation.applyPluginsBailResult (/Users/ruka/Projects/web/node_modules/webpack/node_modules/tapable/lib/Tapable.js:109:27)
    at sealPart2 (/Users/ruka/Projects/web/node_modules/webpack/lib/Compilation.js:586:10)
    at next (/Users/ruka/Projects/web/node_modules/webpack/node_modules/tapable/lib/Tapable.js:138:11)
    at Compilation.compilation.plugin (/Users/ruka/Projects/web/node_modules/webpack/lib/ProgressPlugin.js:111:6)
    at next (/Users/ruka/Projects/web/node_modules/webpack/node_modules/tapable/lib/Tapable.js:140:14)
    at /Users/ruka/Projects/web/node_modules/extract-text-webpack-plugin/dist/index.js:241:13
    at /Users/ruka/Projects/web/node_modules/extract-text-webpack-plugin/node_modules/async/dist/async.js:421:16
    at iteratorCallback (/Users/ruka/Projects/web/node_modules/extract-text-webpack-plugin/node_modules/async/dist/async.js:998:13)
    at /Users/ruka/Projects/web/node_modules/extract-text-webpack-plugin/node_modules/async/dist/async.js:906:16
    at /Users/ruka/Projects/web/node_modules/extract-text-webpack-plugin/dist/index.js:224:15
    at /Users/ruka/Projects/web/node_modules/extract-text-webpack-plugin/node_modules/async/dist/async.js:421:16
    at iteratorCallback (/Users/ruka/Projects/web/node_modules/extract-text-webpack-plugin/node_modules/async/dist/async.js:998:13)
    at /Users/ruka/Projects/web/node_modules/extract-text-webpack-plugin/node_modules/async/dist/async.js:906:16
    at /Users/ruka/Projects/web/node_modules/extract-text-webpack-plugin/dist/index.js:221:22
    at /Users/ruka/Projects/web/node_modules/extract-text-webpack-plugin/node_modules/async/dist/async.js:3083:16
    at eachOfArrayLike (/Users/ruka/Projects/web/node_modules/extract-text-webpack-plugin/node_modules/async/dist/async.js:1003:9)
    at eachOf (/Users/ruka/Projects/web/node_modules/extract-text-webpack-plugin/node_modules/async/dist/async.js:1051:5)
    at Object.eachLimit (/Users/ruka/Projects/web/node_modules/extract-text-webpack-plugin/node_modules/async/dist/async.js:3145:5)
    at /Users/ruka/Projects/web/node_modules/extract-text-webpack-plugin/dist/index.js:189:29
    at /Users/ruka/Projects/web/node_modules/extract-text-webpack-plugin/node_modules/async/dist/async.js:3083:16
    at eachOfArrayLike (/Users/ruka/Projects/web/node_modules/extract-text-webpack-plugin/node_modules/async/dist/async.js:1003:9)
    at eachOf (/Users/ruka/Projects/web/node_modules/extract-text-webpack-plugin/node_modules/async/dist/async.js:1051:5)
    at Object.eachLimit (/Users/ruka/Projects/web/node_modules/extract-text-webpack-plugin/node_modules/async/dist/async.js:3145:5)

Cannot read property 'forEach' of null

Hi @indutny! Awesome idea for the plugin.

I've tried sticking it into our super large app, but we're getting compilation errors:

[09:47:51][Step 5/6] uncaughtException TypeError: Cannot read property 'forEach' of null
[09:47:51][Step 5/6]     at Module.mergeFrom (/home/teamcity/agent-08/3b0ebbb1933d0dce/node_modules/common-shake/lib/shake/module.js:54:18)
[09:47:51][Step 5/6]     at Analyzer.resolve (/home/teamcity/agent-08/3b0ebbb1933d0dce/node_modules/common-shake/lib/shake/analyzer.js:52:12)
[09:47:51][Step 5/6]     at NormalModuleFactory.params.normalModuleFactory.plugin (/home/teamcity/agent-08/3b0ebbb1933d0dce/node_modules/webpack-common-shake/lib/shake/plugin.js:55:22)
[09:47:51][Step 5/6]     at NormalModuleFactory.applyPluginsBailResult (/home/teamcity/agent-08/3b0ebbb1933d0dce/node_modules/tapable/lib/Tapable.js:109:27)
[09:47:51][Step 5/6]     at applyPluginsAsyncWaterfall (/home/teamcity/agent-08/3b0ebbb1933d0dce/node_modules/webpack/lib/NormalModuleFactory.js:80:32)
[09:47:51][Step 5/6]     at /home/teamcity/agent-08/3b0ebbb1933d0dce/node_modules/tapable/lib/Tapable.js:204:11
[09:47:51][Step 5/6]     at NormalModuleFactory.params.normalModuleFactory.plugin (/home/teamcity/agent-08/3b0ebbb1933d0dce/node_modules/webpack/lib/CompatibilityPlugin.js:52:5)
[09:47:51][Step 5/6]     at NormalModuleFactory.applyPluginsAsyncWaterfall (/home/teamcity/agent-08/3b0ebbb1933d0dce/node_modules/tapable/lib/Tapable.js:208:13)
[09:47:51][Step 5/6]     at resolver (/home/teamcity/agent-08/3b0ebbb1933d0dce/node_modules/webpack/lib/NormalModuleFactory.js:74:11)
[09:47:51][Step 5/6]     at process.nextTick (/home/teamcity/agent-08/3b0ebbb1933d0dce/node_modules/webpack/lib/NormalModuleFactory.js:205:8)
[09:47:51][Step 5/6]     at _combinedTickCallback (internal/process/next_tick.js:134:7)
[09:47:51][Step 5/6]     at process._tickCallback (internal/process/next_tick.js:201:9)

We're on Webpack 3 and CommonShakePlugin 1.1.1.

False bailout for `require`.

I'm seeing

WARNING in global bailout from webpack-common-shake
Invalid use of `require` at [/path/to//esm/src/module/make-require-function.js:35:9]

Which looks like this. It's being babel transpiled back to cjs and scope hoisted with webpack. The plugin is bailing out because it's seeing the use of require without checking that it's a local reference and not the environment variable.

Shakes exports when they're used

This is the code:

var propTypes={
light:_propTypes2.default.bool,
dark:_propTypes2.default.bool,
inverse:(0,_utils.deprecated)(_propTypes2.default.bool,'Please use the prop "dark"')
}

However, the "exports" in front of "deprecated" in the original file gets shaken out, so when the code is executed it throws an error.

Module parse failed: BASE[type] is not a function

Thanks for all of the work on this repo. I'm getting the following error when applying the plugin to my (fairly large) react + babel application:

"Module parse failed: /Users/ian/dev/redivis/assets/node_modules/babel-loader/lib/index.js??ref--1!/Users/ian/dev/redivis/assets/javascripts/helpers/bulkUploadUserRequirements.js BASE[type] is not a function
You may need an appropriate loader to handle this file type.
TypeError: BASE[type] is not a function
    at c (/Users/ian/dev/redivis/assets/node_modules/common-shake/lib/shake/walk.js:17:15)
    at Object.skipThrough (/Users/ian/dev/redivis/assets/node_modules/acorn/dist/walk.js:162:39)
    at c (/Users/ian/dev/redivis/assets/node_modules/common-shake/lib/shake/walk.js:17:15)
    at Object.base.VariableDeclarator (/Users/ian/dev/redivis/assets/node_modules/acorn/dist/walk.js:239:20)
    at c (/Users/ian/dev/redivis/assets/node_modules/common-shake/lib/shake/walk.js:17:15)
    at Object.base.VariableDeclaration (/Users/ian/dev/redivis/assets/node_modules/acorn/dist/walk.js:235:7)
    at c (/Users/ian/dev/redivis/assets/node_modules/common-shake/lib/shake/walk.js:17:15)
    at Object.skipThrough (/Users/ian/dev/redivis/assets/node_modules/acorn/dist/walk.js:162:39)
    at c (/Users/ian/dev/redivis/assets/node_modules/common-shake/lib/shake/walk.js:17:15)
    at Object.base.Program.base.BlockStatement (/Users/ian/dev/redivis/assets/node_modules/acorn/dist/walk.js:171:7)"

A similar error is being thrown across about a dozen modules; the error message really doesn't make any sense to me. Everything works fine if I remove the plugin.

Let me know if I can provide any further details; many thanks.

Support Webpack v4

Support for webpack v4 in order to use with uglify-es (uglify-v3) that supports async/await

[QUESTION] Compatibility with other plugins

Hello,

Thank you for writing such a great library.

I've just added this to my production build with webpack 3 and saw quite a difference:
michaelBenin/react-ssr-spa@e8d6039

I tried adding the shake plugin to the development build, (Added here: https://github.com/michaelBenin/react-ssr-spa/blob/master/gulpfile.babel.js/configs/webpack.config.js#L38) and found there must be a conflict with some other plugins as there was an error which reported sourcemaps incorrectly.

Is there any other types of webpack plugins that this library may be incompatible with?

Thank you again.

One entry points spoils shaking for another one

My app has multiple entry points (that are built into separate independent bundles) that share the common library.
If one of the entry points uses some exports from that library all the bundles will get such export persisted even if it's not used by them.

Example:

  • the library defines 3 exports A, B, C
  • entry1 uses all 3 of them, all 3 are not shaken in the bundle1
  • entry2 only uses C, but still all 3 are present in the bundle2

Demo repo: https://github.com/emirotin/common-shake-issue

Handle stage-3 dyanmic import.

Here is the Code snippet from which I'm 100% sure this came from:

const asyncRenderView = (viewName, wire, model) =>
  import(`../../shared/view/${viewName}.js`).then(renderFn => renderFn(wire, model));

const view = {
  about: (wire, model) => asyncRenderView('about', wire, model),
  summary: (wire, model) => asyncRenderView('summary', wire, model),
  item: (wire, model) => asyncRenderView('item', wire, model),
  comment: (wire, model) => asyncRenderView('comment', wire, model),
  user: (wire, model) => asyncRenderView('user', wire, model),
  next: (wire, model) => asyncRenderView('next', wire, model)
};

Following error:

ERROR in ./client/js/render.js
Module parse failed: /Users/req88847/Code/@viper/viper-news/node_modules/babel-loader/lib/index.js!/Users/req88847/Code/@viper/viper-news/client/js/render.js Unknown node type Import.
You may need an appropriate loader to handle this file type.
Error: Unknown node type Import.
    at Controller.traverse (/Users/req88847/Code/@viper/viper-news/node_modules/estraverse/estraverse.js:521:31)
    at Object.traverse (/Users/req88847/Code/@viper/viper-news/node_modules/estraverse/estraverse.js:713:27)
    at Analyzer.sift (/Users/req88847/Code/@viper/viper-news/node_modules/common-shake/lib/shake/analyzer.js:177:14)
    at Analyzer.run (/Users/req88847/Code/@viper/viper-news/node_modules/common-shake/lib/shake/analyzer.js:35:8)
    at Parser.parser.plugin (/Users/req88847/Code/@viper/viper-news/node_modules/webpack-common-shake/lib/shake/plugin.js:17:19)
    at Parser.applyPluginsBailResult (/Users/req88847/Code/@viper/viper-news/node_modules/tapable/lib/Tapable.js:109:27)
    at Parser.parse (/Users/req88847/Code/@viper/viper-news/node_modules/webpack/lib/Parser.js:1366:11)
    at doBuild (/Users/req88847/Code/@viper/viper-news/node_modules/webpack/lib/NormalModule.js:293:17)
    at runLoaders (/Users/req88847/Code/@viper/viper-news/node_modules/webpack/lib/NormalModule.js:207:11)
    at /Users/req88847/Code/@viper/viper-news/node_modules/loader-runner/lib/LoaderRunner.js:370:3
    at iterateNormalLoaders (/Users/req88847/Code/@viper/viper-news/node_modules/loader-runner/lib/LoaderRunner.js:211:10)
    at iterateNormalLoaders (/Users/req88847/Code/@viper/viper-news/node_modules/loader-runner/lib/LoaderRunner.js:218:10)
    at /Users/req88847/Code/@viper/viper-news/node_modules/loader-runner/lib/LoaderRunner.js:233:3
    at Object.context.callback (/Users/req88847/Code/@viper/viper-news/node_modules/loader-runner/lib/LoaderRunner.js:111:13)
    at Object.module.exports (/Users/req88847/Code/@viper/viper-news/node_modules/babel-loader/lib/index.js:183:8)
    at LOADER_EXECUTION (/Users/req88847/Code/@viper/viper-news/node_modules/loader-runner/lib/LoaderRunner.js:119:14)
    at runSyncOrAsync (/Users/req88847/Code/@viper/viper-news/node_modules/loader-runner/lib/LoaderRunner.js:120:4)
    at iterateNormalLoaders (/Users/req88847/Code/@viper/viper-news/node_modules/loader-runner/lib/LoaderRunner.js:229:2)
    at Array.<anonymous> (/Users/req88847/Code/@viper/viper-news/node_modules/loader-runner/lib/LoaderRunner.js:202:4)
    at Storage.finished (/Users/req88847/Code/@viper/viper-news/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:38:15)
    at /Users/req88847/Code/@viper/viper-news/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:69:9
    at /Users/req88847/Code/@viper/viper-news/node_modules/graceful-fs/graceful-fs.js:78:16
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:439:3)
 @ ./client/js/index.js 2:13-32

This is most likely because of the acorn dynamic-import plugin we are using so users can support
import().

Cannot read property 'has' of null || TypeError: Cannot read property 'has' of null

Hi @indutny.
I've updated again, however the build still crashes. Sorry ;)

[Step 5/6] [Compilation] : Cannot read property 'has' of null || TypeError: Cannot read property 'has' of null
    at Module.isUsed (/home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/common-shake/lib/shake/module.js:78:19)
    at analyzer.run.getDeclarations.filter (/home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/webpack-common-shake/lib/shake/replacement.js:100:26)
    at Array.filter (native)
    at ReplacementModule.source (/home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/webpack-common-shake/lib/shake/replacement.js:99:25)
    at ModuleTemplate.render (/home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/webpack/lib/ModuleTemplate.js:14:31)
    at /home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/webpack/lib/Template.js:110:28
    at Function.from (native)
    at ChunkTemplate.renderChunkModules (/home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/webpack/lib/Template.js:107:26)
    at ChunkTemplate.render (/home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/webpack/lib/ChunkTemplate.js:16:30)
    at Compilation.createChunkAssets (/home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/webpack/lib/Compilation.js:1255:35)
    at sealPart2 (/home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/webpack/lib/Compilation.js:628:10)
    at next (/home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/tapable/lib/Tapable.js:138:11)
    at Compilation.compilation.plugin (/home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/webpack/lib/ProgressPlugin.js:111:6)
    at Compilation.applyPluginsAsyncSeries (/home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/tapable/lib/Tapable.js:142:13)
    at Compilation.seal (/home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/webpack/lib/Compilation.js:578:8)
    at /home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/webpack/lib/Compiler.js:510:16
    at /home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/tapable/lib/Tapable.js:225:11
    at _combinedTickCallback (internal/process/next_tick.js:134:7)
    at process._tickCallback (internal/process/next_tick.js:201:9)

ChunkRenderError: 
    at Compilation.createChunkAssets (/home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/webpack/lib/Compilation.js:1274:22)
    at sealPart2 (/home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/webpack/lib/Compilation.js:628:10)
    at next (/home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/tapable/lib/Tapable.js:138:11)
    at Compilation.compilation.plugin (/home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/webpack/lib/ProgressPlugin.js:111:6)
    at Compilation.applyPluginsAsyncSeries (/home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/tapable/lib/Tapable.js:142:13)
    at Compilation.seal (/home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/webpack/lib/Compilation.js:578:8)
    at /home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/webpack/lib/Compiler.js:510:16
    at /home/teamcity/agent-09/3b0ebbb1933d0dce/node_modules/tapable/lib/Tapable.js:225:11
    at _combinedTickCallback (internal/process/next_tick.js:134:7)
    at process._tickCallback (internal/process/next_tick.js:201:9)

Support dynamic import using stable syntax

import for dynamic imports is currently not stable, and so many codebases still use the old one for code splitting, namely AMD-style require:

require(['static-dep-A', 'static-dep-B'], function (staticDepA, staticDepB) {
...
});

Currently all these cases cause webpack-common-shake to bail out even though they're likely optimizable in the same way.

Issues with redux-observable

Windows 10
Node 8.4
NPM 5.3
redux-observable 0.16

Been tracking down why random bits of my page were breaking when using the minified bundle, and it turns out this plugin breaks combineEpics, as well as something else I can't run down. All I know is removing this plugin resolves my issues. Will add more details if I find them, but for now I just have to deploy my stuff. Thanks for the plugin, it's been 100% awesome up till this one use case!

Support recursive imports

Instead of bailing out on code like this:

// root.js
require('./lib').a.b

// lib.js
exports.a = require('./a');

// a.js
exports.b = 1;

We should recognize recursive pattern and store uses in a.js.

Uncaught TypeError when using this plugin

I'm working on a starter for React + ReasonML + webpack. I wanted to use webpack-common-shake plugin. Unfortunately, when enabled, I get this TypeError:

Uncaught TypeError: this.number is not a function

How to reproduce?

Expected result:

You can see Hello world, Anne! in the browser. No errors in the console

Current result:

Uncaught TypeError: this.number is not a function
    at Object.numberString (main.js:4385)
    at new SockJS (main.js:64)
    at socket (socket.js:7)
    at Object.<anonymous> (main.js:10282)
    at Object.<anonymous> (main.js:10307)
    at __webpack_require__ (bootstrap b5203ed…:669)
    at fn (bootstrap b5203ed…:87)
    at Object.<anonymous> (main.js:17077)
    at __webpack_require__ (bootstrap b5203ed…:669)
    at validateFormat (bootstrap b5203ed…:715)

Workaround:

Disable webpack-common-shake plugin in webpack.config.js

False bailout with deep require

// root.js
const { foo } = require('./bundle.js');

// bundle.js
module.exports = {
  foo: require('./foo.js'),
  bar: require('./bar.js'),
}

In this case bar is not exported, but required and minifier can't eliminate this code.

Compiled code looks like this

/***/ (function(module, exports, __webpack_require__) {

module.exports = {
    "bar": ((__webpack_require__(4)),null),
    foo: __webpack_require__(5)
};

/***/ }),

Usage with babel and uglifyJs

Hi, may I ask for some more hints on how to use this together with other webpack ecosystem things? (Already looked at webpack-common-shake-demo.

More specifically,

  • An example config with babel-loader?
  • Does it matter for the order of plugins? Should ShakePlugin go before or after UglifyJSPlugin?

Thanks!

Bundle error

After adding this plugin to my wp config i get the following error:

montogeek ~/project [02:30 PM]→ 😀  (feat/tests-ci)
👉  NODE_ENV=production yarn build
yarn build v0.24.4
$ rm -rf dist/* && npm run build:client

> [email protected] build:client /Users/montogeek/project
> webpack --config webpack.config.js --display-error-details --display-used-exports

Hash: 261625c02a2a1e40084c
Version: webpack 2.6.1
Time: 1004ms
        Asset       Size  Chunks             Chunk Names
    bundle.js    4.92 kB       0  [emitted]  main
bundle.js.map    10.7 kB       0  [emitted]  main
   index.html  697 bytes          [emitted]
   [0] ./main.js 4.35 kB {0} [built] [failed] [1 error]
   [1] multi ./main.js 28 bytes {0} [built]

ERROR in ./main.js
Module parse failed: /Users/montogeek/project/node_modules/babel-loader/lib/index.js!/Users/montogeek/project/src/main.js ImportDeclaration should appear when the mode is ES6 and in the module context.
You may need an appropriate loader to handle this file type.
AssertionError: ImportDeclaration should appear when the mode is ES6 and in the module context.
    at Referencer.ImportDeclaration (/Users/montogeek/project/node_modules/escope/lib/referencer.js:591:34)
    at Referencer.Visitor.visit (/Users/montogeek/project/node_modules/esrecurse/esrecurse.js:122:34)
    at Referencer.Visitor.visitChildren (/Users/montogeek/project/node_modules/esrecurse/esrecurse.js:101:38)
    at Referencer.Program (/Users/montogeek/project/node_modules/escope/lib/referencer.js:419:18)
    at Referencer.Visitor.visit (/Users/montogeek/project/node_modules/esrecurse/esrecurse.js:122:34)
    at Object.analyze (/Users/montogeek/project/node_modules/escope/lib/index.js:153:16)
    at Analyzer.gather (/Users/montogeek/project/node_modules/common-shake/lib/shake/analyzer.js:45:26)
    at Analyzer.run (/Users/montogeek/project/node_modules/common-shake/lib/shake/analyzer.js:34:8)
    at Parser.parser.plugin (/Users/montogeek/project/node_modules/webpack-common-shake/lib/shake/plugin.js:15:19)
    at Parser.applyPluginsBailResult (/Users/montogeek/project/node_modules/tapable/lib/Tapable.js:109:27)
    at Parser.parse (/Users/montogeek/project/node_modules/webpack/lib/Parser.js:1358:11)
    at doBuild (/Users/montogeek/project/node_modules/webpack/lib/NormalModule.js:288:17)
    at runLoaders (/Users/montogeek/project/node_modules/webpack/lib/NormalModule.js:206:11)
    at /Users/montogeek/project/node_modules/loader-runner/lib/LoaderRunner.js:370:3
    at iterateNormalLoaders (/Users/montogeek/project/node_modules/loader-runner/lib/LoaderRunner.js:211:10)
    at iterateNormalLoaders (/Users/montogeek/project/node_modules/loader-runner/lib/LoaderRunner.js:218:10)
    at /Users/montogeek/project/node_modules/loader-runner/lib/LoaderRunner.js:233:3
    at Object.context.callback (/Users/montogeek/project/node_modules/loader-runner/lib/LoaderRunner.js:111:13)
    at Object.module.exports (/Users/montogeek/project/node_modules/babel-loader/lib/index.js:172:8)
    at LOADER_EXECUTION (/Users/montogeek/project/node_modules/loader-runner/lib/LoaderRunner.js:119:14)
    at runSyncOrAsync (/Users/montogeek/project/node_modules/loader-runner/lib/LoaderRunner.js:120:4)
    at iterateNormalLoaders (/Users/montogeek/project/node_modules/loader-runner/lib/LoaderRunner.js:229:2)
    at Array.<anonymous> (/Users/montogeek/project/node_modules/loader-runner/lib/LoaderRunner.js:202:4)
    at Storage.finished (/Users/montogeek/project/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:38:15)
    at /Users/montogeek/project/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:69:9
    at /Users/montogeek/project/node_modules/graceful-fs/graceful-fs.js:78:16
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:439:3)
 @ multi ./main.js
Child html-webpack-plugin for "index.html":
       [0] ../~/lodash/lodash.js 540 kB {0} [built]
       [1] ../~/html-webpack-plugin/lib/loader.js!./index.ejs 1.41 kB {0} [built]
       [2] ../~/webpack/buildin/global.js 509 bytes {0} [built]
       [3] ../~/webpack/buildin/module.js 517 bytes {0} [built]
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! [email protected] build:client: `webpack --config webpack.config.js --display-error-details --display-used-exports`
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the [email protected] build:client script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/montogeek/.npm/_logs/2017-06-28T19_30_56_471Z-debug.log
error Command failed with exit code 2.

webpack.config.js

const prodConfig = {
  entry: {
    main: ['./main.js']
  },
  context: path.resolve(__dirname, 'src'),
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  devtool: 'source-map',
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader'
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: [
            {
              loader: 'css-loader',
              options: {
                minimize: true
              }
            },
            {
              loader: 'postcss-loader'
            }
          ]
        })
      },
      {
        test: /\.(png|jpg|gif|eot|ttf|woff|woff2)$/,
        loader: 'url-loader',
        options: {
          limit: 10000
        }
      },
      {
        test: /\.svg$/,
        use: 'raw-loader'
      }
    ]
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': { NODE_ENV: JSON.stringify('production') },
      HOST: JSON.stringify(host)
    }),
    new ExtractTextPlugin('styles.css'),
    new HtmlWebpackPlugin({
      template: './index.ejs',
      files: {
        css: ['style.css'],
        js: ['bundle.js']
      },
      frameTrackerContentUrl: frameTrackerContentUrl,
      production: true
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: { warnings: false },
      sourceMap: true
    }),
    new ShakePlugin()
  ]
}

main.js

import React from 'react'
import ReactDOM from 'react-dom'
import { AppContainer } from 'react-hot-loader'
import App from './containers/App'

const rootEle = document.getElementById('app')

const onConfigurationLoaded = callback => {
  let configurationLoadedTimer = setInterval(() => {
    if (window.globalThing && window.globalThing) {
      clearInterval(configurationLoadedTimer)
      callback()
    }
  }, 100)
}

const render = Component => {
  ReactDOM.render(
    <AppContainer>
      <Component />
    </AppContainer>,
    rootEle
  )
}

onConfigurationLoaded(() => {
  render(App)
})

if (module.hot) {
  module.hot.accept('./containers/App', () => {
    render(App)
  })
}

[email protected]
[email protected]
webpack 2.6.1

Looks like it is overriden loaders configuration?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.