Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to apply different loaders depending on entry?

I have a Webpack configuration with 2 entries:

const path = require('path');

module.exports = {
  entry: {
    public: './src/public.js',
    admin: './src/adminPanel.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [{
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env', {
                targets: {
                  browsers: ['last 5 years']
                }
              }]
            ]
          }
        }]
      }
    ]
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'
  }
};

It produces 2 files: a script for the public pages and a script for the admin panel. The entries import another JS files including some shared files. I need the public script to support many browsers and the admin panel script to support only the latest Chrome.

I want to achieve it by using different browsers setting depending on the entry so that if a JS file is used in the public entry, it is loaded with one settings, and if a file is used in the admin entry, it is loaded with the other settings. How to do it in Webpack 4?

I know I can solve my problem by exporting 2 Webpack configurations but I wonder how to use different loaders or adjust a loader options basing on the entry file.

like image 788
Finesse Avatar asked Feb 24 '19 06:02

Finesse


1 Answers

I need the public script to support many browsers and the admin panel script to support only the latest Chrome. I want to achieve it by using different browsers setting depending on the entry.

babel supports multiple configurations per directory (recursively up to it finds a babel configuration file up to a package.json is found:

Babel loads .babelrc (and .babelrc.js / package.json#babel) files by searching up the directory structure starting from the "filename" being compiled (limited by the caveats below). This can be powerful because it allows you to create independent configurations for subsections of a package. Source: babel docs

Currently you have placed your babel configuration in your webpack configuration which is applied project wide. What you could do is remove the babel config from your webpack, place your adminPanel.js and public.js in separate directories with each their own .babelrc (or other babel config) file which have different targets for @babel/presets-env.

.
├── src
|   ├── admin
|   |   ├── adminPanel.js
|   |   ├── .babelrc
|   |
|   ├── public
|   |   ├── public.js
|   |   ├── .babelrc
|
├── package.json

Your ./src/admin/.babelrc could look like:

{
    "presets": [["@babel/preset-env", {
        "targets": "chrome 70"
    }]]
}

And your ./src/public/.babelrc:

{
    "presets": [["@babel/preset-env", {
        "targets": "last 5 years"
    }]]
}

I've just tried this with the following code in both ./src/admin/adminPanel.js and ./src/public/public.js

[1, 2, 3].map(num => `number ${num}`)

let [x, y, z] = [2, 4, 6]

Which webpack and babel have transformed to

// ./dist/admin.js
[1, 2, 3].map(num => `number ${num}`);
let [x, y, z] = [2, 4, 6];

and

// ./dist/public.js
[1, 2, 3].map(function (num) {
  return "number ".concat(num);
});
var x = 2,
    y = 4,
    z = 6;

Hope it helps.

like image 178
axm__ Avatar answered Nov 12 '22 05:11

axm__