Search code examples
gulp

Gulp require alias


I am looking for a safe way of doing require aliases using gulp. The idea is similar to what webpack offers with resolve alias.

For example, I put on my source code something like require('@plugin/utils') and it is translated to something of my choice, like require('$/plugins/longer/namespace/utils'). You probably have noticed that it does not match to any actual file path, and that is intentional (they are tiddlywiki files if anyone is interested). The best thing I found is gulp-replace, but that relies on strings replacements at worst and regular expressions at best. Ideally I would want something more reliable, something that is AST aware,so I'm sure that I never replace the wrong string (for example, a template string). I am also using babel, so if there is a babel plugin that I can use I will also be happy about that. As a last resort I may try to write some babel plugin or a gulp plugin using esprima, but esprima is not up to modern JS standard (doesn't parse object spread) and I would prefer creating another tool.

Thanks in advance


Solution

  • Finally I found a babel module (babel-plugin-module-resolver) that I can integrate with gulp, and with some extra configuration magic with eslint.

    So, this is what I added to my gulp pipeline (simplified)

        const babelCfg = {
        plugins: [[
                require.resolve('babel-plugin-module-resolver'),
                {
                    root: [ `${pluginSrc}/**` ],
                    alias: { '@plugin': `$:/plugins/${pluginNamespace}` },
                    loglevel: 'silent',
                }
              ]],
          };
       return gulp
            .src(`${pluginSrc}/**/*.js`)
            .pipe(babel(babelCfg))
            .pipe(gulp.dest(outPath.dist));
    

    That converts all the references to require('@plugin/xxxx') with the proper path. With some extra configuration you can even make eslint warn you about bad path resolutions. You need to configure it differently because eslint needs the real path, while the output files needs a special namespace. After installing both eslint-import-resolver-babel-module and eslint-plugin-import this is what you should add to your eslint config to make it work:

    plugins:
        - import
    
    env:
        node: true
        browser: true
    
    settings:
        import/resolver:
            babel-module:
                root: ./src/**
                alias:
                    "@plugin": ./src/the/real/path
    
    rules:
        import/no-unresolved: [2, { commonjs: true }]