Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

webpack import only variable value

I'm compiling code that needs the version value from package.json:

import {version} from '../package.json';
export default {version};

and when I look at the .js file that webpack outputs I see the whole package.json there!

How can I avoid this?

My setup is:

plugins: [
    new webpack.DefinePlugin({
        'process.env.NODE_ENV': '"production"'
    }),
    new webpack.optimize.UglifyJsPlugin({
        compress: {
            warnings: false
        }
    }),
    new CompressionPlugin({
        asset: '[path].gz[query]',
        algorithm: 'gzip',
        test: /\.(js|css)$/,
        threshold: 10240,
        minRatio: 0.8
    }),
]

My webpack version is 3.8.1

like image 538
Rikard Avatar asked Nov 07 '17 19:11

Rikard


2 Answers

What I usually do is take advantage of the DefinePlugin

// webpack.config.js
// getting the version
const package = require("./package.json");
const version = package.version;

plugins: [
    new webpack.DefinePlugin({
        'process.env.NODE_ENV': '"production"',
        'process.env.VERSION': version,
    }),
    new webpack.optimize.UglifyJsPlugin({
        compress: {
            warnings: false
        }
    }),
    new CompressionPlugin({
        asset: '[path].gz[query]',
        algorithm: 'gzip',
        test: /\.(js|css)$/,
        threshold: 10240,
        minRatio: 0.8
    }),
]

Now in your code all you gotta do is use process.env.VERSION and you it will output your packages version.

Hope it helped

like image 58
João Cunha Avatar answered Sep 19 '22 02:09

João Cunha


Modern webpack versions support Tree shaking (https://webpack.js.org/guides/tree-shaking/ ), but it works only if export directives are configured by special scheme, includes independent named import for each entity. In that case webpack can perform analyze dependencies graph and include only required entities. Also, import directive does not support destructing - it's only syntax for named import, so large JS object will be always imported in monolithic style.

Import as value is unavailable by definition, because webpack performs only bundling for set of files with source code and maybe custom resources dependencies. Real imports in ES6 modules, which today are already supported on most platforms, also do not provide values imports - instead it's binding. https://ponyfoo.com/articles/es6-modules-in-depth#bindings-not-values.

Of course, original problem can be solved by webpack replace or alias plugins. Just store version in some independent file or string constant and substitute it due bundling. Most straightforward solution is

import version from 'PACKAGE_VERSION'

and then configure external with callback https://webpack.js.org/configuration/externals/ like that

externals: [
  function(context, request, callback) {
    if (request === 'PACKAGE_VERSION'){
      return callback(null, 'exports.default = ' + JSON.stringify(JSON.parse(fs.readFileSync('package.json')).version));
    }
    callback();
  }
],
like image 26
Vladislav Ihost Avatar answered Sep 22 '22 02:09

Vladislav Ihost