Search code examples
testingwebpackbuildjshintwebpack-3

How to jsHint two different folders with Webpack?


In short, I need to jshint tests specifications in parallel with the package sources during the build process.

Using the Webpack 3, how to make jshint-loader to watch out for two different folders with two different .jshintrc files? One pack of sources with .jshintrc is in the ./src folder, which is bundling to the end distributive, and the other one pack with another .jshintrc is in the ./test folder, which does not mentioned in the Webpack config (Karma handles it).

I tried the following two approaches, and both of them processed ./src only, they didn't do anything with ./test. First version of Webpack config:

entry: {
    'ui-scroll': path.resolve(__dirname, '../src/ui-scroll.js'),
    'ui-scroll-grid': path.resolve(__dirname, '../src/ui-scroll-grid.js')
},    
module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: { presets: ['es2015'] }
      },
      {
        enforce: 'pre',
        test: /\.js$/,
        include: path.resolve(__dirname, '../src'),
        use: [{ loader: 'jshint-loader' }]
      },
      {
        enforce: 'pre',
        test: /\.js$/,
        include: path.resolve(__dirname, '../test'),
        use: [{ loader: 'jshint-loader' }]
      }
    ]
},
// ...

The second version of Webpack config differs in the module-rules part:

module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: { presets: ['es2015'] }
      },
      {
        enforce: 'pre',
        test: /\.js$/,
        include: [
          path.resolve(__dirname, '../src'),
          path.resolve(__dirname, '../test')
        ],
        use: [{ loader: 'jshint-loader' }]
      }
    ]
},
// ...

But as I said this doesn't work. Full config/sources could be obtained from this repository. So is it possible to fix my approach or do I need try something quite different?


Solution

  • After some research we were able to solve this issue by splitting the situation into two parts: jshinting tests during production build (only once, the distributive is on the disk) and during development processes (watch mode, the distributive is in memory).

    1. Production build. This is pretty simple, because jshit should be executed only once. After adding jshint as a dependency to the npm-package –

    npm install --save-dev jshint
    

    it could be prepended to the build script –

    "hint-tests": "jshint --verbose test",
    "build": "npm run hint-tests && npm run prod-build && npm run prod-test"
    

    None of prod-build and prod-test processes know about jshint.

    2. Development. The solution is to add a new entry point via glob:

    entry: {
      'ui-scroll': path.resolve(__dirname, '../src/ui-scroll.js'),
      'ui-scroll-grid': path.resolve(__dirname, '../src/ui-scroll-grid.js')
      'test': glob.sync(path.resolve(__dirname, 'test/*.js')) // development only!
    }
    

    It should be done only for the development environment otherwise you'll get an extra bundle in the distributive folder. So we have it in memory; it's affecting the dev processes a bit due to extra bundling, but the difference is insignificant due to this occurs in-memory only. Then using jshint-loader let's add one more rule to the module section of the webpack config:

    module: {
      rules: [
        {
          test: /\.js$/,
          exclude: /node_modules/,
          loader: 'babel-loader',
          options: { presets: ['es2015'] }
        },
        { // this is both for prod and dev environments
          enforce: 'pre',
          test: /\.js$/,
          include: path.resolve(__dirname, 'src'),
          use: [{ loader: 'jshint-loader' }]
        },
        { // this is only for dev environment
          enforce: 'pre',
          test: /\.js$/,
          include: path.resolve(__dirname, 'test'),
          use: [{ loader: 'jshint-loader' }]
        }
      ]
    }
    

    There may be too many logs in the console output, especialy during the dev-server work, so it could be helpful to limit output via stats property:

      stats: {
        modules: false,
        errors: true,
        warnings: true
      }