Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use webpack.NormalModuleReplacementPlugin for optional conditional file loading

Tags:

webpack

What I'm hoping to achieve is to have a single codebase for a web app and cordova app.

I want to have a folder/file structure that looks like this:

- components
  - component1.js
  - component2.js
  - component2.cordova.js

Ideally I want to continue to just use import Component2 from 'component2' wherever I import a component.

I will have a separate webpack.config file for each build, so was hoping I could get the cordova webpack config to look first for component1.cordova.js, and if it doesn't exist, fall back to component1.js.

It seems like webpack.NormalModuleReplacementPlugin can do the looking for the cordova version, but I'm not sure if/how I can have it fall back to component1.js if component1.cordova.js doesn't exist.

like image 865
GusRuss89 Avatar asked Jan 13 '17 08:01

GusRuss89


2 Answers

I believe no plugin is needed.

Here's what you need to do:

resolve: {
        root: [SRC_PATH, NODE_MODULES_PATH],
        fallback: NODE_MODULES_PATH,        
        extensions: ['.cordova.js','.js'],
}

The key is the extensions param. As you may have noticed, extensions are probed in the given order.

If you ever need to explicitly require one of the .js or .cordova.js you should specify the full file name, e.g : require('components/c1.cordova.js')

Note: resolve is at the root of the config object.

So the answer ends here, but there's more.

The added bonus of the resolve.root param is that you can now import by using paths relative to SRC_PATH instead of the messy ../../../

Of course, you need to have NODE_MODULES_PATH and SRC_PATH defined beforehand.

With this config you can write in any file in the SRC_PATH tree something like this:

import c from 'components/component1';

or

var c = require('components/component1')
like image 199
Tudor Ilisoi Avatar answered Oct 04 '22 13:10

Tudor Ilisoi


I had the same problem, this is my solution:

const fs = require('fs');
const path = require('path');
...
new webpack.NormalModuleReplacementPlugin(/\.ts$/, function(resource) {
    if (!resource.request.endsWith('.cordova.ts')) {
        var file_for_cordova = resource.request.replace(/\.ts$/, '.cordova.ts');
        if (fs.existsSync(path.resolve(resource.context, file_for_cordova))){
            resource.request = file_for_cordova;
          }
      }
}),

I think, it still not perfect and you can improve it

like image 43
Andrey Omelyanuk Avatar answered Oct 04 '22 11:10

Andrey Omelyanuk