loading...

0cjs! Webpack4 tutorial: Building React app without config file.

shisama profile image Masashi Hirano Updated on ・3 min read

On January, webpack4 was pre-released as beta.0.
On February 25, webpack4 was released 🎉
Webpack4 doesn't need a config file by default!
It made me excited and I tried to build My React app without webpack config.

About webpack4

Please refer to the links below.

Other tools

  • babel-preset-env
  • babel-preset-react
  • flow

My webpack config

const path = require('path');
const webpack = require('webpack');

module.exports = {
  entry: {
    'index': [
      path.resolve(__dirname, 'src/index.js')
    ]
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'public'),
    publicPath: '/',
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
    }),
    new webpack.optimize.UglifyJsPlugin(),
  ],
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        use: 'babel-loader',
      },
    ]
  },
  resolve: {
    extensions: ['.js', '.jsx'],
  },
};

How to use webpack4

Install

You have to install webpack 4 and webpack-cli.
From webpack 4, webpack-cli is necessary to execute webpack on command line.

npm install --save-dev webpack webpack-cli

Build without config

module-bind

First, I executed webpack with no config and no options.
Error occurred.

Module parse failed: Unexpected token (15:6)
You may need an appropriate loader to handle this file type.
|   render() {
|     return (
|       <div>

Above error means that babel is invalid and webpack doesn't analyze jsx syntax.
With config, below code solves this error.

module: {
  rules: [
    {
      test: /\.(js|jsx)$/,
      use: 'babel-loader',
    },
  ]
},

if you want to use babel-loader, you need to use --module-bind options.
usage: --module-bind {extension}={loader-name}

webpack --module-bind 'js=babel-loader' --module-bind 'jsx=babel-loader'

resolve-extensions

Though --module-bind option is valid, other error occurred.

Module not found: Error: Can't resolve './Foo' in '/path/to/src'

This error means that import modules failed,
The reason why this error occurred is that I've omitted extensions like below code.

import Foo from 'components/Foo'

With config, below soloves this error.

resolve: {
  extensions: ['.js', '.jsx'],
},

Webpack4 has --resolve-extensions cli-option.
Setup extensions that should be used to resolve modules (e.g. --resolve-extensions .js,.jsx)
Using --module-bind and --resolve-extensions options,

webpack --module-bind 'js=babel-loader' --module-bind 'jsx=babel-loader' --resolve-extensions .js,.jsx 

mode

Ok, Errors have been resolved 😊
But warning is displayed.

WARNING in configuration
The 'mode' option has not been set. Set 'mode' option to 'development' or 'production' to enable defaults for this environment. 

quote from Release Note v4.0.0-beta.0

  • You have to choose (mode or --mode) between two modes now: production or development
    • production enables all kind of optimizations to generate optimized bundles
    • development enables comments and hint for development and enables the eval devtool
    • WIP: addition hints in development mode
    • production doesn't support watching, development is optimized for fast incremental rebuilds
    • production also enables module concatenating (Scope Hoisting)
    • You can configure this in detail with the flags in optimization.* (build your custom mode)
    • process.env.NODE_ENV are set to production or development (only in built code, not in config)
    • There is a hidden none mode which disables everything

--mode option has to be added.

webpack --module-bind 'js=babel-loader' --module-bind 'jsx=babel-loader' --resolve-extensions .js,.jsx --mode production

entry

You can specify the entry point.
--entry src means that the entry point is src/index.js.
--entry src/foo.js means that the entry point is src/foo.js

output

Also, you can specify the output point.
--output public means that the output directory is public.
--output public/index.bundle.js means that the output directory is public and output file name is index.bundle.js.
-o is the shorthand of --output.

Filnal

webpack --module-bind 'js=babel-loader' --module-bind 'jsx=babel-loader' --resolve-extensions .js,.jsx --mode production --entry ./src --output public/index.bundle.js

Other options

You can know the other options with --help option.

webpack --help

Further reading

Thank you.

Discussion

markdown guide
 

webpack-dev-middleware + webpack-dev-server +

server.js:
...
app.use(webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath
}));
...

webpack.config.js:
...
new webpack.DefinePlugin({'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)}),
or as u did mention
new webpack.DefinePlugin({'process.env.NODE_ENV': JSON.stringify('production')}),
...

Gives me:
WARNING in configuration
The 'mode' option has not been set. Set 'mode' option to 'development' or 'production' to enable defaults for this environment.

package.json:
...
"webpack": "4.0.1",
"webpack-cli": "2.0.9"
"webpack-dev-middleware": "3.0.0",
"webpack-dev-server": "3.1.0",
...
it seems most latest versions...

How to set 'mode' while using webpack-dev-middleware + webpack-dev-server, any suggestions? ;)

p.s. webpack via command line works fine ;)

 

Sorry to reply late.
If your webpack.config.js doesn't have 'mode' property, you have to add 'mode' property into your webpack.config.js.

The below is an example.

module.exports = {
  mode: 'production', // <= It is necessary to resolve the warning
  entry: {
    'index': [
      path.resolve(__dirname, 'src/index.js')
    ]
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'public'),
    publicPath: '/',
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
    })
  ],
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        use: 'babel-loader',
      },
    ]
  },
  resolve: {
    extensions: ['.js', '.jsx'],
  },
};

Thank you for reading this post.

 

Hello, Masashi Hirano.

It's seems im miss something in the past, here is examples ) github.com/webpack/webpack/tree/ma...

Anyway, thx ) for response.