Обновитесь до WebPack5 и внедрите Jest

#reactjs #webpack #gulp #babeljs

Вопрос:

У меня есть старое репо, и мы решили реализовать Jest. Мы столкнулись с проблемами, из-за которых нам пришлось перейти на WebPack 5.

gulpfile.js

 var gulp = require('gulp')
var utils = require('gulp-util')
var revAll = require('gulp-rev-all')
var del = require('del')

// Webpack build
var webpack = require('webpack')
var CompressionPlugin = require('compression-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
// Build configurations.
var path = require('path')

var Config = {
  srcDir: path.resolve('./src'),
  publicDir: path.resolve('./public'),
  distDir: path.resolve('./dist')
}

var contentBase = __dirname   '/public'
var httpRedirectContentBase = __dirname   '/https-redirect'

// Environment detection
var currentEnv = process.env.NODE_ENV || 'development'
utils.log('Environment:', utils.colors.blue(currentEnv))

var webpackConfig = {
  target: 'node',
  devtool: 'eval-source-map',
  entry: path.join(__dirname, 'src', 'index.js'),
  mode: process.env.NODE_ENV || 'development',

  output: {
    globalObject: 'this',
    path: Config.publicDir   '/',
    publicPath: '',
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /.(js|jsx)$/,
        exclude: /node_modules/,
        use: ['babel-loader']
      },
      {
        test: /.(css|scss|sass)$/,
        use: ['css-loader', 'sass-loader']
      }
    ]
  },
  resolve: {
    extensions: ['', '.jsx', '.js', '.json', 'scss'],
    modules: [path.resolve(__dirname, 'src'), 'node_modules']
  },
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    port: 9000
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, 'src', 'index.js')
    }),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoEmitOnErrorsPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify(currentEnv)
      }
    })
  ].concat(
    currentEnv === 'production' ? [
      new webpack.optimize.DedupePlugin(),
      new webpack.optimize.UglifyJsPlugin({
        mangle: { except: ['require', 'export', 'import', '$super'] },
        compress: {
          sequences: true,
          dead_code: true,
          conditionals: true,
          booleans: true,
          unused: true,
          if_return: true,
          join_vars: true,
          drop_console: true,
          warnings: false
        }
      }),
      new CompressionPlugin({
        asset: '{file}.gz',
        algorithm: 'gzip',
        threshold: 10240,
        minRatio: 0.8
      })
    ] : []
  )
}

gulp.task('webpack:build', function(callback) {
  webpackConfig.output.path = Config.publicDir
  webpackConfig.devtool = 'source-map'

  webpack(webpackConfig, function(err, stats) {
    if (err) throw new utils.PluginError('webpack:build', err)

    utils.log('Webpack', stats.toString({
      colors: true,
      chunks: false
    }))

    callback()
  })
})

// Webpack server
var WebpackDevServer = require('webpack-dev-server')

gulp.task('webpack:serve', function() {
  var hostname = '0.0.0.0'
  var port = 4567
  var compiler = webpack(webpackConfig)

  var server = new WebpackDevServer(compiler, {
    contentBase: contentBase,
    publicPath: webpackConfig.output.publicPath,
    historyApiFallback: true,
    noInfo: true,
    hot: true,
    stats: {
      colors: true,
      chunks: false
    }
  })
  server.listen(port, hostname, function(err) {
    if (err) throw new utils.PluginError('webpack:serve', err)

    utils.log('Starting', utils.colors.red('Webpack Dev Server'))
    utils.log(
      'Listening on',
      utils.colors.red('http://'   hostname   ':'   port)
    )
  })
})

gulp.task('webpack:https-redirect-serve', function() {
  var httpsRedirectWebpackConfig = {
    devtool: 'eval-source-map',
    output: {
      path: path.resolve('./https-redirect/'),
      publicPath: ''
    }
  }

  var hostname = '0.0.0.0'
  var port = 4568
  var compiler = webpack(httpsRedirectWebpackConfig)

  var server = new WebpackDevServer(compiler, {
    contentBase: httpRedirectContentBase,
    publicPath: webpackConfig.output.publicPath,
    historyApiFallback: true,
    noInfo: true,
    hot: true,
    https: true,
    stats: {
      colors: true,
      chunks: false
    }
  })
  server.listen(port, hostname, function(err) {
    if (err) throw new utils.PluginError('webpack:serve', err)

    utils.log('Starting', utils.colors.red('Webpack Dev Server'))
    utils.log(
      'Listening on',
      utils.colors.red('https://'   hostname   ':'   port)
    )
  })
})

// ESLint. I can't figure out where gulp-eslint is trying to find the .eslintignore
// file, so I'm relying on gulp for exclusions for now. Excluding tests because
// otherwise it screams about Jest/Jasmine magic.
var eslint = require('gulp-eslint')

gulp.task('eslint', function() {
  return gulp.src(
    [
      Config.srcDir   '/**/*.{js,jsx}',
      '!**/tests/**'
    ]
  )
  .pipe(eslint())
  .pipe(eslint.format())
})

// Watch.
gulp.task('watch', function() {
  gulp.watch(Config.srcDir   '/**/*.{js,jsx}', ['eslint'])
})

gulp.task('clean:dist', function () {
  return del([Config.distDir])
})

gulp.task('revision', ['build', 'clean:dist'], function() {
  gulp.src(
    [
      Config.publicDir   '/**/*',
      '!**/config.example.js',
      '!**/*.js.map'
    ]
  )
  .pipe(revAll.revision({
    dontGlobal: [/^/(version|config).js/],
    dontRenameFile: [/^/index.html/g]
  }))
  .pipe(gulp.dest(Config.distDir))
})

gulp.task('build', ['eslint', 'webpack:build'])
gulp.task('dist', ['build', 'revision'])
gulp.task('default', ['webpack:serve', 'webpack:https-redirect-serve', 'build', 'watch'])
 

.babelrc

 {
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react"
  ],
  "plugins": [
    "@babel/plugin-proposal-class-properties"
  ]
}
 

пакет.json

 {
  "version": "1.3.0",
  "engines": {
    "node": ">=5.12.0"
  },
  "scripts": {
    "build": "gulp build amp;amp; node -e 'process.stdout.write(JSON.stringify({version: require(`./package.json`).version}))' > public/version.json",
    "start": "gulp",
    "lint": "gulp eslint",
    "test": "npm run lint amp;amp; npm run test:web amp;amp; npm run test:tape",
    "test:coverage": "nyc report --reporter=text-lcov",
    "test:tape": "babel-tape-runner src/**/*.test.js | faucet",
    "test:web": "jest --coverage",
    "test:e2e": "./node_modules/protractor/bin/protractor e2e/config/protractor-conf.js",
    "test:driver-update": "./node_modules/protractor/bin/webdriver-manager update",
  },
  "dependencies": {
    "async": "^1.5.2",
    "classnames": "^2.2.5",
    "csv-stringify": "^1.0.4",
    "global": "^4.3.0",
    "google-client-api": "~1.0.4",
    "lodash": "^3.10.0",
    "moment": "~2.10.6",
    "prettysize": "0.0.3",
    "prop-types": "^15.7.2",
    "react": "^15.1.0",
    "react-date-picker": "~5.3.28",
    "react-dom": "^15.1.0",
    "react-google-maps": "^4.11.0",
    "react-mixin": "^3.0.5",
    "react-modal": "^3.11.1",
    "react-redux": "^4.4.5",
    "react-router": "^3.0.5",
    "react-select": "^2.4.4",
    "react-tabs": "^3.1.1",
    "redux": "^3.5.2",
    "redux-logger": "^3.0.6",
    "redux-thunk": "^2.1.0",
    "reselect": "^2.5.1",
    "superagent": "^2.0.0",
    "wolfy87-eventemitter": "^5.0.0"
  },
  "devDependencies": {
    "@babel/core": "^7.14.6",
    "@babel/node": "^7.0.0",
    "@babel/plugin-proposal-class-properties": "^7.14.5",
    "@babel/plugin-transform-runtime": "^7.14.5",
    "@babel/preset-env": "^7.14.7",
    "@babel/preset-react": "^7.14.5",
    "@babel/register": "^7.0.0",
    "@types/enzyme": "^3.10.8",
    "@types/jest": "^26.0.23",
    "JSONPath": "^0.11.2",
    "autoprefixer-loader": "^3.2.0",
    "babel-core": "^7.0.0-bridge.0",
    "babel-eslint": "^10.1.0",
    "babel-jest": "^23.6.0",
    "babel-loader": "^8.0.4",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-tape-runner": "^3.0.0",
    "chai": "^3.5.0",
    "chai-as-promised": "^6.0.0",
    "chai-things": "^0.2.0",
    "compression-webpack-plugin": "^8.0.1",
    "css-loader": "^0.15.1",
    "cucumber": "^4.2.1",
    "cucumber-pretty": "^1.4.0",
    "del": "^2.2.2",
    "enzyme": "^3.11.0",
    "enzyme-adapter-react-15": "^1.4.3",
    "eslint": "^7.30.0",
    "eslint-plugin-react": "^5.1.1",
    "faker": "^4.1.0",
    "faucet": "0.0.1",
    "generic-cucumber-protractor-framework": "1.8.5",
    "gulp": "^3.9.1",
    "gulp-eslint": "^2.0.0",
    "gulp-rev-all": "^0.9.7",
    "gulp-util": "^3.0.7",
    "html-webpack-plugin": "^5.3.2",
    "jest": "^27.0.5",
    "jsx-loader": "^0.13.2",
    "node-sass": "^3.13.0",
    "node-sass-globbing": "0.0.23",
    "nyc": "^6.6.1",
    "object-assign": "^4.1.0",
    "protractor": "^5.4.4",
    "protractor-cucumber-framework": "^4.2.0",
    "protractor-hotkeys": "0.0.5",
    "protractor-jasmine2-screenshot-reporter": "^0.3.0",
    "protractor-multicapabilities-htmlreporter_v2": "0.0.6",
    "protractor-multiple-cucumber-html-reporter-plugin": "^1.3.0",
    "react-hot-loader": "^1.3.0",
    "react-test-renderer": "^15.7.0",
    "redux-mock-store": "^1.5.4",
    "request-promise": "^4.2.0",
    "sass-loader": "^12.1.0",
    "sinon": "^7.2.2",
    "style-loader": "0.13.1",
    "tap": "^5.7.2",
    "tape": "^4.5.1",
    "ts-jest": "^27.0.3",
    "typescript": "^4.3.4",
    "webpack": "^5.43.0",
    "webpack-dev-server": "^3.11.2"
  }
}
 

Everytime when I fix something something else will be broken. So I am taking a wild hunch that there are some configuration «boo-boo» that I have made. The error right now is as follows:

 yarn run v1.22.10
warning package.json: No license field
$ gulp build amp;amp; node -e 'process.stdout.write(JSON.stringify({version: require(`./package.json`).version}))' > public/version.json
[12:35:58] Environment: development
[12:35:58] Using gulpfile ~/Documents/Tab/Tab-Git/control-centre/gulpfile.js
[12:35:58] Starting 'eslint'...
[12:35:59] Starting 'webpack:build'...
[12:36:15] Finished 'eslint' after 17 s
[12:36:18] Webpack assets by status 5.01 MiB [cached] 2 assets
runtime modules 23.3 KiB 11 modules
modules by path ./node_modules/ 3.2 MiB
  javascript modules 3.03 MiB
    cacheable modules 3.03 MiB 566 modules
    2 modules
  json modules 173 KiB 3 modules
modules by path ./src/ 1.13 MiB
  modules by path ./src/components/ 1000 KiB 53 modules
  modules by path ./src/apis/*.js 72.5 KiB 10 modules
  modules by path ./src/*.js 1.26 KiB
    ./src/index.js 117 bytes [built] [code generated]
    ./src/createStore.js 995 bytes [built] [code generated]
    ./src/config.js 174 bytes [built] [code generated]
  ./src/stylesheets/index.scss 78.2 KiB [built] [code generated]
17 modules

WARNING in ./node_modules/formidable/lib/file.js 1:43-50
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
 @ ./node_modules/formidable/lib/incoming_form.js 7:11-28
 @ ./node_modules/formidable/lib/index.js 1:19-58
 @ ./node_modules/superagent/lib/node/index.js 7:17-38
 @ ./src/apis/google-authentication.js 1:0-33 31:4-15 62:4-15
 @ ./src/apis/authentication.js 4:0-55 30:6-29 128:6-24 173:6-23
 @ ./src/components/views/app/index.jsx 10:0-58 37:0-33
 @ ./src/index.js 2:0-41 3:0-7

WARNING in ./node_modules/formidable/lib/incoming_form.js 1:43-50
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
 @ ./node_modules/formidable/lib/index.js 1:19-58
 @ ./node_modules/superagent/lib/node/index.js 7:17-38
 @ ./src/apis/google-authentication.js 1:0-33 31:4-15 62:4-15
 @ ./src/apis/authentication.js 4:0-55 30:6-29 128:6-24 173:6-23
 @ ./src/components/views/app/index.jsx 10:0-58 37:0-33
 @ ./src/index.js 2:0-41 3:0-7

WARNING in ./node_modules/formidable/lib/json_parser.js 1:43-50
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
 @ ./node_modules/formidable/lib/incoming_form.js 11:17-52
 @ ./node_modules/formidable/lib/index.js 1:19-58
 @ ./node_modules/superagent/lib/node/index.js 7:17-38
 @ ./src/apis/google-authentication.js 1:0-33 31:4-15 62:4-15
 @ ./src/apis/authentication.js 4:0-55 30:6-29 128:6-24 173:6-23
 @ ./src/components/views/app/index.jsx 10:0-58 37:0-33
 @ ./src/index.js 2:0-41 3:0-7

WARNING in ./node_modules/formidable/lib/querystring_parser.js 1:43-50
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
 @ ./node_modules/formidable/lib/incoming_form.js 9:24-73
 @ ./node_modules/formidable/lib/index.js 1:19-58
 @ ./node_modules/superagent/lib/node/index.js 7:17-38
 @ ./src/apis/google-authentication.js 1:0-33 31:4-15 62:4-15
 @ ./src/apis/authentication.js 4:0-55 30:6-29 128:6-24 173:6-23
 @ ./src/components/views/app/index.jsx 10:0-58 37:0-33
 @ ./src/index.js 2:0-41 3:0-7

4 WARNINGS in child compilations (Use 'stats.children: true' resp. '--stats-children' for more details)

4 warnings have detailed information that is not shown.
Use 'stats.errorDetails: true' resp. '--stats-error-details' to show it.

ERROR in   Error: document is not defined

  - index.js:129860
    /Users/Rohith/Documents/Tab/Tab-Git/control-centre/src/index.js:129860:64

  - index.js:129861
    /Users/Rohith/Documents/Tab/Tab-Git/control-centre/src/index.js:129861:3

  - index.js:129864
    /Users/Rohith/Documents/Tab/Tab-Git/control-centre/src/index.js:129864:12

  - index.js:142 HtmlWebpackPlugin.evaluateCompilationResult
    [control-centre]/[html-webpack-plugin]/index.js:142:28

  - index.js:324 Promise.resolve.then
    [control-centre]/[html-webpack-plugin]/index.js:324:26

  - next_tick.js:68 process._tickCallback
    internal/process/next_tick.js:68:7



webpack 5.43.0 compiled with 1 error and 8 warnings in 19012 ms
[12:36:18] Finished 'webpack:build' after 20 s
[12:36:18] Starting 'build'...
[12:36:18] Finished 'build' after 21 μs
✨  Done in 21.48s.