assembler
assembler

Reputation: 3300

Webpack 4 Module parse failed: Unexpected token

I have a React.js project based on React-Boilerplate 3.7.0 and I'm using its own webpack configurations files, that is to say webpack.base.babel.js, webpack.dev.babel.js and webpack.prod.babel.js. I've been looking for a solution in the web for a while and I was unable to find a way to solve this. In https://gitter.im/webpack/webpack there is a banner saying:

For questions please post on Stack Overflow and use the 'webpack' tag

So here I'm, once again. Webpack compiles the project with no errors and no warnings in development (if I run npm start), but if I run npm run build or npm run-script build it tells me:

    > [email protected] prebuild /home/user/project
    > npm run build:clean

    > [email protected] build:clean /home/user/project
    > rimraf ./build

    > [email protected] build /home/user/project
    > cross-env NODE_ENV=production webpack --config internals/webpack/webpack.prod.babel.js --color -p --progress --hide-modules --display-optimization-bailout

    Hash: c6a237769a07ad14e665                                                           
    Version: webpack 4.27.1
    Time: 40850ms
    Built at: 2019-01-28 09:40:17
     250 assets
    Entrypoint main = runtime~main.d96d827d2fca77de74ac.js vendor.4d1e1f30cd3a7c98cfd8.chunk.js main.01e9d47c88b2e7155bd5.chunk.js

    ERROR in ./node_modules/jqwidgets-scripts/jqwidgets-react/react_jqxgrid.js 1216:12
    Module parse failed: Unexpected token (1216:12)
    You may need an appropriate loader to handle this file type.
    |     render() {
    |         return (
    >             <div id={this.state.id}>{this.props.value}{this.props.children}</div>
    |         )
    |     };
     @ ./app/containers/xxxxxxx/index.js 38:0-70 343:37-44
     ...
     @ ./app/containers/MainLayout/_nav.js
     @ ./app/containers/MainLayout/index.js
     @ ./app/containers/MainLayout/Loadable.js
     @ ./app/containers/App/index.js
     @ ./app/app.js
     @ multi ./node_modules/react-app-polyfill/ie11.js ./app/app.js
...

This is my package.json file:

{
  "name": "react-boilerplate",
  "version": "3.7.0",
  "description": "A highly scalable, offline-first foundation with the best DX and a focus on performance and best practices",
  "repository": {
    "type": "git",
    "url": "git://github.com/react-boilerplate/react-boilerplate.git"
  },
  "engines": {
    "npm": ">=5",
    "node": ">=8.10.0"
  },
  "author": "Max Stoiber",
  "license": "MIT",
  "scripts": {
    "analyze:clean": "rimraf stats.json",
    "preanalyze": "npm run analyze:clean",
    "analyze": "node ./internals/scripts/analyze.js",
    "extract-intl": "node ./internals/scripts/extract-intl.js",
    "npmcheckversion": "node ./internals/scripts/npmcheckversion.js",
    "preinstall": "npm run npmcheckversion",
    "prebuild": "npm run build:clean",
    "build": "cross-env NODE_ENV=production webpack --config internals/webpack/webpack.prod.babel.js --color -p --progress --hide-modules --display-optimization-bailout",
    "build:clean": "rimraf ./build",
    "start": "cross-env NODE_ENV=development env-cmd .env node server",
    "start:tunnel": "cross-env NODE_ENV=development ENABLE_TUNNEL=true node server",
    "start:production": "npm run test && npm run build && npm run start:prod",
    "start:prod": "cross-env NODE_ENV=production node server",
    "presetup": "npm i chalk shelljs",
    "setup": "node ./internals/scripts/setup.js",
    "clean": "shjs ./internals/scripts/clean.js",
    "clean:all": "npm run analyze:clean && npm run test:clean && npm run build:clean",
    "generate": "plop --plopfile internals/generators/index.js",
    "lint": "npm run lint:js",
    "lint:css": "stylelint './app/**/*.js'",
    "lint:eslint": "eslint --ignore-path .gitignore --ignore-pattern internals/scripts",
    "lint:eslint:fix": "eslint --ignore-path .gitignore --ignore-pattern internals/scripts --fix",
    "lint:js": "npm run lint:eslint -- . ",
    "lint:staged": "lint-staged",
    "pretest": "npm run test:clean && npm run lint",
    "test:clean": "rimraf ./coverage",
    "test": "cross-env NODE_ENV=test jest --coverage",
    "test:watch": "cross-env NODE_ENV=test jest --watchAll",
    "coveralls": "cat ./coverage/lcov.info | coveralls",
    "prettify": "prettier --write"
  },
  "lint-staged": {
    "*.js": [
      "npm run lint:eslint:fix",
      "git add --force"
    ],
    "*.json": [
      "prettier --write",
      "git add --force"
    ]
  },
  "pre-commit": "lint:staged",
  "resolutions": {
    "babel-core": "7.0.0-bridge.0"
  },
  "dependencies": {
    "@coreui/coreui": "^2.1.4",
    "@coreui/coreui-plugin-chartjs-custom-tooltips": "^1.2.0",
    "@coreui/icons": "^0.3.0",
    "@coreui/react": "^2.1.1",
    "ajv": "^6.6.1",
    "babel-polyfill": "^6.26.0",
    "block-ui": "^2.70.1",
    "bootstrap": "^4.1.3",
    "chalk": "^2.4.1",
    "chart.js": "^2.7.3",
    "classnames": "^2.2.6",
    "compression": "^1.7.3",
    "connected-react-router": "^4.5.0",
    "core-js": "^2.6.0",
    "env-cmd": "^8.0.2",
    "exports-loader": "^0.7.0",
    "flag-icon-css": "^3.2.1",
    "font-awesome": "^4.7.0",
    "fontfaceobserver": "2.0.13",
    "history": "^4.7.2",
    "hoist-non-react-statics": "3.0.1",
    "immutable": "^3.8.2",
    "intl": "^1.2.5",
    "invariant": "^2.2.4",
    "ip": "^1.1.5",
    "is-url-external": "^1.0.3",
    "isnumeric": "^0.3.3",
    "jquery": "^3.3.1",
    "jqwidgets-scripts": "^6.2.0",
    "loadable-components": "^2.2.3",
    "lodash": "^4.17.11",
    "minimist": "1.2.0",
    "moment": "^2.22.2",
    "numeral": "^2.0.6",
    "prop-types": "^15.6.2",
    "react": "^16.6.3",
    "react-chartjs-2": "^2.7.4",
    "react-dom": "^16.6.3",
    "react-helmet": "^5.2.0",
    "react-hot-loader": "^4.6.3",
    "react-intl": "^2.7.2",
    "react-loadable": "^5.5.0",
    "react-redux": "^5.1.1",
    "react-router-dom": "^4.3.1",
    "react-sizeme": "^2.5.2",
    "reactstrap": "^6.5.0",
    "redux": "^4.0.1",
    "redux-immutable": "^4.0.0",
    "redux-saga": "^0.16.2",
    "reselect": "4.0.0",
    "resize-sensor": "0.0.6",
    "sanitize.css": "4.1.0",
    "simple-line-icons": "^2.4.1",
    "styled-components": "^4.1.2",
    "uuid": "^3.3.2",
    "warning": "^4.0.2"
  },
  "devDependencies": {
    "@babel/cli": "7.1.2",
    "@babel/core": "7.1.2",
    "@babel/plugin-proposal-class-properties": "7.1.0",
    "@babel/plugin-proposal-export-namespace-from": "^7.2.0",
    "@babel/plugin-syntax-dynamic-import": "7.0.0",
    "@babel/plugin-transform-modules-commonjs": "7.2.0",
    "@babel/plugin-transform-react-constant-elements": "7.0.0",
    "@babel/plugin-transform-react-inline-elements": "7.0.0",
    "@babel/polyfill": "^7.0.0",
    "@babel/preset-env": "7.1.0",
    "@babel/preset-react": "7.0.0",
    "@babel/register": "7.0.0",
    "add-asset-html-webpack-plugin": "3.1.1",
    "babel-core": "7.0.0-bridge.0",
    "babel-eslint": "10.0.1",
    "babel-loader": "8.0.4",
    "babel-plugin-dynamic-import-node": "2.2.0",
    "babel-plugin-lodash": "3.3.4",
    "babel-plugin-react-intl": "3.0.1",
    "babel-plugin-react-transform": "3.0.0",
    "babel-plugin-styled-components": "1.10.0",
    "babel-plugin-transform-react-remove-prop-types": "0.4.19",
    "circular-dependency-plugin": "5.0.2",
    "compare-versions": "3.4.0",
    "compression-webpack-plugin": "2.0.0",
    "copy-webpack-plugin": "^4.6.0",
    "coveralls": "3.0.2",
    "cross-env": "^5.2.0",
    "css-loader": "1.0.0",
    "enzyme": "3.7.0",
    "enzyme-adapter-react-16": "1.6.0",
    "enzyme-to-json": "3.3.4",
    "eslint": "5.7.0",
    "eslint-config-airbnb": "17.1.0",
    "eslint-config-airbnb-base": "13.1.0",
    "eslint-config-prettier": "3.1.0",
    "eslint-import-resolver-webpack": "0.10.1",
    "eslint-plugin-import": "^2.14.0",
    "eslint-plugin-jsx-a11y": "6.1.2",
    "eslint-plugin-prettier": "3.0.0",
    "eslint-plugin-react": "7.11.1",
    "eslint-plugin-redux-saga": "0.9.0",
    "express": "^4.16.4",
    "file-loader": "2.0.0",
    "html-loader": "0.5.5",
    "html-webpack-plugin": "3.2.0",
    "http-proxy-middleware": "^0.19.1",
    "image-webpack-loader": "^4.6.0",
    "imports-loader": "0.8.0",
    "jest-cli": "23.6.0",
    "jest-styled-components": "6.2.2",
    "lint-staged": "7.3.0",
    "ngrok": "3.1.0",
    "node-plop": "0.16.0",
    "node-sass": "^4.11.0",
    "null-loader": "0.1.1",
    "offline-plugin": "5.0.5",
    "optimize-css-assets-webpack-plugin": "^5.0.1",
    "plop": "2.1.0",
    "pre-commit": "1.2.2",
    "prettier": "1.14.3",
    "react-app-polyfill": "0.1.3",
    "react-test-renderer": "16.6.0",
    "rimraf": "2.6.2",
    "sass-loader": "^7.1.0",
    "shelljs": "^0.8.3",
    "style-loader": "0.23.1",
    "stylelint": "9.6.0",
    "stylelint-config-recommended": "2.1.0",
    "stylelint-config-styled-components": "0.1.1",
    "stylelint-processor-styled-components": "1.5.0",
    "svg-url-loader": "2.3.2",
    "terser-webpack-plugin": "1.1.0",
    "uglifyjs-webpack-plugin": "^2.0.1",
    "url-loader": "1.1.2",
    "webpack": "^4.27.1",
    "webpack-cli": "^3.1.2",
    "webpack-dev-middleware": "3.4.0",
    "webpack-hot-middleware": "2.24.3 ",
    "webpack-pwa-manifest": "3.7.1",
    "whatwg-fetch": "3.0.0"
  }
}

This is my webpack.base.babel.js file:

const path = require('path');
const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const config = require('../../server/config');

module.exports = options => ({
  mode: options.mode,
  entry: options.entry,
  output: Object.assign(
    {
      // Compile into js/build.js
      path: path.resolve(process.cwd(), 'build'),
      publicPath: '/',
    },
    options.output,
  ), // Merge with env dependent settings
  optimization: options.optimization,
  module: {
    rules: [
      {
        test: /\.js$|\.jsx$/, // Transform all .js files required somewhere with Babel
        exclude: /node_modules\/(?!(jqwidgets-scripts\/jqwidgets-react)\/).*/,
        use: {
          loader: 'babel-loader',
          options: options.babelQuery,
        },
      },
      // {
      //   test: /\.js$|\.jsx$/,
      //   exclude: '/node_modules',
      //   include: '/jqwidgets-scripts/jqwidgets-react',
      //   use: {
      //     loader: 'babel-loader',
      //     options: options.babelQuery
      //   }
      // },
      {
        // Preprocess our own .css files
        // This is the place to add your own loaders (e.g. sass/less etc.)
        // for a list of loaders, see https://webpack.js.org/loaders/#styling
        test: /\.scss$/,
        exclude: /node_modules/,
        use: ['style-loader', 'css-loader', 'sass-loader'],
      },
      {
        // Preprocess 3rd party .css files located in node_modules
        test: /\.css$/,
        include: /node_modules/,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /\.(eot|otf|ttf|woff|woff2)$/,
        use: 'file-loader',
      },
      {
        test: /\.svg$/,
        use: [
          {
            loader: 'svg-url-loader',
            options: {
              // Inline files smaller than 10 kB
              limit: 10 * 1024,
              noquotes: true,
            },
          },
        ],
      },
      {
        test: /\.(jpg|png|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              // Inline files smaller than 10 kB
              limit: 10 * 1024,
            },
          },
          {
            loader: 'image-webpack-loader',
            options: {
              mozjpeg: {
                enabled: false,
                // NOTE: mozjpeg is disabled as it causes errors in some Linux environments
                // Try enabling it in your environment by switching the config to:
                // enabled: true,
                // progressive: true,
              },
              gifsicle: {
                interlaced: false,
              },
              optipng: {
                optimizationLevel: 7,
              },
              pngquant: {
                quality: '65-90',
                speed: 4,
              },
            },
          },
        ],
      },
      {
        test: /\.html$/,
        use: 'html-loader',
      },
      {
        test: /\.(mp4|webm)$/,
        use: {
          loader: 'url-loader',
          options: {
            limit: 10000,
          },
        },
      },
    ],
  },
  plugins: options.plugins.concat([
    // Always expose NODE_ENV to webpack, in order to use `process.env.NODE_ENV`
    // inside your code for any environment checks; Terser will automatically
    // drop any unreachable code.

    /* new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
    }), */

    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify(config.env),
        HOST: JSON.stringify(config.server_host),
        PORT: JSON.stringify(config.server_port),
      },
    }),

    new webpack.NamedModulesPlugin(),
    new CopyWebpackPlugin([{ from: 'static' }]),
  ]),
  resolve: {
    modules: ['node_modules', 'app'],
    extensions: ['.js', '.jsx', '.react.js'],
    mainFields: ['browser', 'jsnext:main', 'main'],
    alias: {
      moment$: 'moment/moment.js',
    },
  },
  devtool: options.devtool,
  target: 'web', // Make web variables accessible to webpack, e.g. window
  performance: options.performance || {},
});

Here there is a regular expression to exclude node_modules but to include jqwidgets-scripts/jqwidgets-react and next there is a commented block with another approach, unsuccessfully as well.

And this is webpack.prod.babel.js:

// Important modules this config uses
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackPwaManifest = require('webpack-pwa-manifest');
const OfflinePlugin = require('offline-plugin');
const { HashedModuleIdsPlugin } = require('webpack');
const TerserPlugin = require('terser-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');

module.exports = require('./webpack.base.babel')({
  mode: 'production',

  // In production, we skip all hot-reloading stuff
  entry: [
    require.resolve('react-app-polyfill/ie11'),
    path.join(process.cwd(), 'app/app.js'),
  ],

  // Utilize long-term caching by adding content hashes (not compilation hashes) to compiled assets
  output: {
    filename: '[name].[chunkhash].js',
    chunkFilename: '[name].[chunkhash].chunk.js',
  },

  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          warnings: false,
          compress: {
            comparisons: false,
          },
          parse: {},
          mangle: true,
          output: {
            comments: false,
            ascii_only: true,
          },
        },
        parallel: true,
        cache: true,
        sourceMap: true,
      }),
    ],
    nodeEnv: 'production',
    sideEffects: true,
    concatenateModules: true,
    splitChunks: {
      chunks: 'all',
      minSize: 30000,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      name: true,
      cacheGroups: {
        commons: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendor',
          chunks: 'all',
        },
        main: {
          chunks: 'all',
          minChunks: 2,
          reuseExistingChunk: true,
          enforce: true,
        },
      },
    },
    runtimeChunk: true,
  },

  plugins: [
    // Minify and optimize the index.html
    new HtmlWebpackPlugin({
      template: 'app/index.html',
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeRedundantAttributes: true,
        useShortDoctype: true,
        removeEmptyAttributes: true,
        removeStyleLinkTypeAttributes: true,
        keepClosingSlash: true,
        minifyJS: true,
        minifyCSS: true,
        minifyURLs: true,
      },
      inject: true,
    }),

    // Put it in the end to capture all the HtmlWebpackPlugin's
    // assets manipulations and do leak its manipulations to HtmlWebpackPlugin
    new OfflinePlugin({
      relativePaths: false,
      publicPath: '/',
      appShell: '/',

      // No need to cache .htaccess. See http://mxs.is/googmp,
      // this is applied before any match in `caches` section
      excludes: ['.htaccess'],

      caches: {
        main: [':rest:'],

        // All chunks marked as `additional`, loaded after main section
        // and do not prevent SW to install. Change to `optional` if
        // do not want them to be preloaded at all (cached only when first loaded)
        additional: ['*.chunk.js'],
      },

      // Removes warning for about `additional` section usage
      safeToUseOptionalCaches: true,
    }),

    new CompressionPlugin({
      algorithm: 'gzip',
      test: /\.js$|\.css$|\.html$/,
      threshold: 10240,
      minRatio: 0.8,
    }),

    new WebpackPwaManifest({
      name: 'React Boilerplate',
      short_name: 'React BP',
      description: 'My React Boilerplate-based project!',
      background_color: '#fafafa',
      theme_color: '#b1624d',
      inject: true,
      ios: true,
      icons: [
        {
          src: path.resolve('app/images/icon-512x512.png'),
          sizes: [72, 96, 128, 144, 192, 384, 512],
        },
        {
          src: path.resolve('app/images/icon-512x512.png'),
          sizes: [120, 152, 167, 180],
          ios: true,
        },
      ],
    }),

    new HashedModuleIdsPlugin({
      hashFunction: 'sha256',
      hashDigest: 'hex',
      hashDigestLength: 20,
    }),
  ],

  performance: {
    assetFilter: assetFilename =>
      !/(\.map$)|(^(main\.|favicon\.))/.test(assetFilename),
  },
});

and finally my babel.config.js:

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        modules: false,
      },
    ],
    '@babel/preset-react',
  ],
  plugins: [
    'styled-components',
    '@babel/plugin-proposal-export-namespace-from',
    '@babel/plugin-proposal-class-properties',
    '@babel/plugin-syntax-dynamic-import',
  ],
  env: {
    production: {
      only: ['app'],
      plugins: [
        'lodash',
        'transform-react-remove-prop-types',
        '@babel/plugin-transform-react-inline-elements',
        '@babel/plugin-transform-react-constant-elements',
      ],
    },
    test: {
      plugins: [
        '@babel/plugin-transform-modules-commonjs',
        'dynamic-import-node',
      ],
    },
  },
};

What am I missing here? am I doing something wrong? How can I get this working in production?

Upvotes: 0

Views: 3798

Answers (1)

d7my
d7my

Reputation: 197

I used the same boilerplate [email protected] and it works fine. Since i can't look at your code, I think it's related to jqwidgets-scripts, why trying to transpile it that way? What you need to do is to remove it from webpack.config files and import it in you codebase, as mentioned in the docs

import JqxProgressBar from '../../../jqwidgets-react/react_jqxprogressbar.js';
import JqxButton from '../../../jqwidgets-react/react_jqxbuttons.js';
import JqxCheckBox from '../../../jqwidgets-react/react_jqxcheckbox.js';

EDIT: So based on this to fix that, you have to update your webpack.base.babel.js file:

{
     test: /\.js$/,
     exclude: /node_modules/,
     use: {
        loader: 'babel-loader',
          options: options.babelQuery,
     },
}

and in your code you can start using jqwidgets-react directly

import JqxBarGauge from 'jqwidgets-scripts/jqwidgets-react/react_jqxbargauge.js'

Upvotes: 1

Related Questions