Lin Nerdy’s Road to Webpack – How to Build

preface

You wish the world, I wish you no bugs. Hello everyone! I’m Lin Dull!

What? ! You still want nerdy to come out and talk to you about Webpack? ! Boy, your idea is very dangerous ❌.

Impossible, the next time you want to see “her” may have to wait until the dull 5000 fans πŸ˜’. There’s no way I’ll ever dress up again πŸ‘š 😊 before that.

So please wake up, the cute girl you see is a handsome boy! This handsome guy he’s got you! Of course, I don’t call myself handsome boy in real life, because I live in Guangdong, so they usually call me Liangzai.

In addition, I updated the github address of the textbook case of “Lin Dull’s Webpack Road Series”. Oh, the previous one was too messy and I deleted it. Now all the textbook cases are the same project, but separate cases can be downloaded in different branches, and all cases are in the trunk. Read README on Github for details. (github.com/LinDaiDai/w…).


Lin Dull to you launched a multi-person learning Webpack

Please select: β˜‘οΈ accept ⭕️ reject


Webpack series introduction

This series documents my learning experience on Webpack. If you want to master Webpack as WELL as I do, I think it will be helpful to you, because the textbook is explained as a Webpack student, and the case demo is very detailed, involving:

  • Based on article
  • Construction Methods (This chapter)
  • Optimize the article
  • Loader article
  • Configuration article

I suggest mark take some time to read it first.

(In fact, this series was written a long time ago, has not been sent out, at that time also wrote a long list of preface can move me, want to read nonsense can click here: GitHub address, but now let’s officially start learning)

All articles are webpack version number ^4.41.5, Webpack-CLI version number ^3.3.10.

In WebPack 3, WebPack itself and its CLI were in the same package, but in version 4, the two were separated, again to allow us to manage them better.

By reading this article you can learn:

  • webpack –watch
  • Webpack dev – server tools
  • Webpack-dev-middle tool, and build local Web server with Express
  • Webpack-merge builds different environments
  • Basic use of process.env.node_env
  • The webpack.defineplugin plugin specifies NODE_ENV

Several development tools

Running the NPM Run build manually becomes cumbersome every time the code is compiled.

Have you ever used scaffolding tools like VUe-CLI to create a local Web server each time you run the NPM run start command and open a port page like localhost:8080? There are also hot updates and other functions.

In fact, the implementation of these functions are vue-CLI internal use of Webpack.

Webpack has several different options to help you automatically compile your code after it changes.

(Section 1 teaching material caseLinDaidai/webpack-example/tree/webpack-server⚠️ : Read the README instructions carefully.)

Webpack’s Watch Mode

In observer mode, just configure a script command in package.json:

"scripts": {
  "watch": "webpack --watch"
}
Copy the code

After using the NPM run watch command, you see the compilation process, but instead of exiting the command line, you monitor the files in real time.

For example, after you modify the local code and save it, it will compile again, without us to manually execute the compilation instructions, the disadvantage is that you need to manually refresh the page to see the changes.

(– Watch can also be shortened to -w)

webpack-dev-server

Using Webpack-dev-server gives you a simple Web server that listens for changes to files and automatically compiles them, as well as automatically refreshes the page. Better than observer mode.

Use steps:

  • $NPM I –save-dev webpack-dev-server

  • Add script command: “start”: “webpack-dev-server –open”

Effect of using this command:

Instead of generating the dist folder, a local Web server localhost:8080 is started

Every time the native code is changed, it is automatically recompiled and the page is refreshed

Other configuration items:

Webpack-dev-server also has many configuration items that can be configured in webpack.config.js

You only need to configure it in devServer, for example:

module.exports = {
    devServer: {
        contentBase: './dist'.// Tell the server where to supply the content
        host: '0.0.0.0'.// The default is localhost
        port: 8000.// Port number, default is 8080
        open: true.// Whether to open the browser automatically
        hot: true.// Enable webPack's module hot replace feature
        hotOnly: true // Do not hot update when compilation fails}}Copy the code

If you use this feature, you’ll notice that it looks a bit like vue-CLI.

More information about devServer configuration can be found here: Server in Development.

webpack-dev-middleware

The basic use

Webpack-dev-middleware is a wrapper that can pass Webpack-processed files to a server.

Webpack-dev-server can start a local Web server because it is used internally, but it can also be used as a package on its own.

Here I will explain with the official case.

Use Webpack-dev-Middleware with Express Server to introduce its functionality.

(Express is a stripped-down Node.js framework that is easy to use if you haven’t used it before.)

Let’s start with my requirements. I want to implement this function:

  • To configure ascriptThe command allows it to run a localwebThe server (i.elocalhost: 3000To view the page)
  • Native code can be recompiled with each change
  • But the page does not refresh automatically
  1. Dependencies required for installation:
$ npm i --save-dev webpack-dev-middleware express
Copy the code
  1. Create a server.js file in the root directory of the project to write the local service:
// server.js
const express = require('express')
const webpack = require('webpack')
const webpackDevMiddleware = require('webpack-dev-middleware')

const app = express()
const config = require('./webpack.config')
const compiler = webpack(config)
// Pass the webPack processed file to a server
app.use(webpackDevMiddleware(compiler))

app.listen(3000.function() {
    console.log('Example app listening on port 3000! \n');
})
Copy the code
  1. Configure the directive to run server.js in package.json:
{
    "scripts": {
        "server": "node server.js"}}Copy the code

PublicPath configuration items

While studying here, I also learned about the publicPath property of output in webpack.config.js.

I didn’t make much sense when I started looking at output.outputPath.

I gave it a try with webpack-dev-Middleware.

First, modify the webpack.config.js configuration:

const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin') module.exports = { entry: { app: './ SRC /index.js', print: './ SRC /print.js'}, devtool: 'inline-source-map', // Only development environment error trace plugins: [ new CleanWebpackPlugin({ cleanAfterEveryBuildPatterns: ['dist'] }), new HtmlWebpackPlugin({ title: 'Webpack Output2', filename: 'index.html', template: 'src/index.html' }) ], output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist'),+ publicPath: '/assets/'}}Copy the code

Then modify server.js:

// server.js const express = require('express') const webpack = require('webpack') const webpackDevMiddleware = require('webpack-dev-middleware') const app = express() const config = require('./webpack.config') const compiler = Webpack (config) // Pass the Webpack processed file to a server app.use(webpackDevMiddleware(Compiler){+,
+ publicPath: config.output.publicPath
+})) app.listen(3000, function() { console.log('Example app listening on port 3000! \n'); })Copy the code

NPM run server (localhost:3000)

Cannot GET /
Copy the code

You need to open localhost:3000/assets/ to see the correct page.

And if there are references to resources in the project, they are automatically prefixed with publicPath:

PNG => Change to /assets/icon.pngCopy the code

This option specifies the public URL for this output directory that is referenced in the browser.

Note ⚠ ️ :

If output.publicPath and Webpack-dev-middleware’s publicPath are not configured, the default is “”, with the root as the configuration item.

If output.publicPath is configured, publicPath in Webpack-dev-middleware needs to be as well.

Second, the construction of different environments

The build goals for development and production environments are very different.

  • In a development environment, you might have the ability to live reloading, hot Module replacement, and so on
  • In the production environment, we are focusing more on smaller bundles, lighter source maps, more optimized resources, etc.

So to follow logical separation, we can write separate WebPack configurations for each environment.

Although we want to write separate configurations, there must be some common configuration items that we can extract and write different configurations in different files.

(Section 2 textbook caseLinDaidai/webpack-example/webpak-merge⚠️ : Read the README instructions carefully.)

webpack-merge

Finally, to merge these configuration items together, we need to use the Webpack-Merge tool.

First install this tool:

$ npm i --save-dev webpack-merge
Copy the code

Then let’s take apart the original webpack.config.js and write it into three different webPack configuration files:

  webpack-demo
  |- package.json
- |- webpack.config.js
+ |- webpack.common.js
+ |- webpack.dev.js
+ |- webpack.prod.js
  |- /dist
  |- /src
    |- index.js
    |- math.js
  |- /node_modules
Copy the code

webpack.common.js:

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
    entry: './src/index.js'.output: {
        filename: '[name].bundle.js'.path: path.resolve(__dirname, 'dist')},plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            title: 'webpack bundle'}})]Copy the code

webpack.dev.js:

const merge = require('webpack-merge')
const commonConfig = require('./webpack.common')

module.exports = merge(commonConfig, {
    devtool: 'inline-source-map'.// Error tracing
    devServer: { // Set the file that webpack-dev-server listens to
        contentBase: './dist'}})Copy the code

webpack.prod.js:

const merge = require('webpack-merge')
const commonConfig = require('./webpack.common')
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')

module.exports = merge(commonConfig, {
    plugins: [
        new UglifyJSPlugin() // Compress the output]})Copy the code

As you can see, webpack-merge combines the configuration of multiple Webpacks into one.

Now let’s configure the package.json script command again:

package.json:

{
    "name": "webpack-bundle"."version": "1.0.0"."description": ""."main": "index.js"."scripts": {
        "start": "webpack-dev-server --open --config webpack.dev.js"."build": "webpack --config webpack.prod.js"
    },
    "keywords": []."author": ""."license": "ISC"."devDependencies": {
        "clean-webpack-plugin": "^ 3.0.0"."html-webpack-plugin": "^ 3.2.0"."uglifyjs-webpack-plugin": "^ 2.2.0." "."webpack": "^ 4.41.5"."webpack-cli": "^ 3.3.10"."webpack-dev-server": "^ 3.10.3"."webpack-merge": "^ 4.2.2." "}}Copy the code
  • performnpm run startFor the development environment, it opens automaticallylocalhost:8080Page and automatic reload function
  • performnpm run buildFor production environment, will be packaged generationdistFolder, andbundleIn thejsIs the compressed code.

process.env.NODE_ENV

Basic usage

The main purpose of process.env.node_env is to help us determine whether it is a development environment or a production environment.

Technically, NODE_ENV is a system environment variable exposed by Node.js to execute scripts.

  1. You can do it at anysrcReference to it in the native code of:
// print.js
export function print() {
    console.log(process.env.NODE_ENV) // development ζˆ–θ€… prodution
}
Copy the code
  1. But you are inwebpack.config.jsYou can’t get it in. Print it outundefined. So code like the following isIt doesn’t work out as expected:
process.env.NODE_ENV === 'production' ? '[name].[hash].bundle.js' : '[name].bundle.js'
Copy the code

Webpack DefinePlugin plug-ins

As mentioned earlier, we can’t get the value of process.env.node_env in webpack.config.js, but we can use the DefinePlugin built into Webpack to modify this variable.

For example, my configuration in webpack.prod.js:

+ const webpack = require('webpack');
  const merge = require('webpack-merge');
  const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
  const commonConfig = require('./webpack.common.js');

  module.exports = merge(commonConfig, {
    devtool: 'source-map',
    plugins: [
      new UglifyJSPlugin({
        sourceMap: true
-})
+}).
+ new webpack.DefinePlugin({
+ 'process.env.NODE_ENV': JSON.stringify('production')
+})]});Copy the code

Process.env.node_env was modified using the webpack.defineplugin () method.

You can set it to json.stringify (‘production’) or you can set it to:

new webpack.DefinePlugin({
      'process.env': {
          'NODE_ENV': `"production"`}})Copy the code

Command line configuration mode mode

In addition to using the webpack.defineplugin plugin to modify the schema of an environment variable, you can also modify it on the command line:

Webpack --mode=production or webpack --mode=developmentCopy the code

–mode is used to set the mode of the environment variable, and the value of process.env.node_env obtained from the local code is the value of mode.

But if you also set it on the command line--mode, used againwebpac.definePluginPlugins, which have a higher priority.

The command line passes environment variables

If we set some variable values on the command line with –env, they will be accessible in our webpack.config.js configuration.

In webpack command line configuration, by setting--envThis allows you to pass in as many environment variables as you need

For example, if I create a new command line:

{
    "scripts": {
        "start": "webpack-dev-server --open --config webpack.dev.js",
        "build": "webpack --config webpack.prod.js",
+ "local": "webpack --env.custom=local --env.production --progress --config webpack.local.js"}}Copy the code

Break it down:

  • --env.custom=localSet a custom property in the environment variablecustom, its value islocal
  • --env.productionSet up theenv.production == true(where theenvDoes not affectprocess.env)
  • --progressPrints a percentage value for compilation progress
  • --config webpack.local.js δ»₯webpack.local.jsPerform a WebPack build on the content in

At the same time I create a wepack.local.js in the project root directory:

const commonConfig = require('./webpack.common')
const merge = require('webpack-merge')

module.exports = env= > {
    console.log('custom: ', env.custom) // 'local'
    console.log('Production: ', env.production) // true
    return merge(commonConfig, {})
}
Copy the code

You can see that it differs from the generic webpack.config.js in that it exports a function that accesses env environment variables.

This allows us to retrieve the variable set on the command line.

The command line passes the environment variable to determine NODE_ENV

NODE_ENV: process.env.node_env: process.env.node_env: process.env.node_env: process.env.node_env: process.env.node_env

process.env.NODE_ENV === 'production' ? '[name].[hash].bundle.js' : '[name].bundle.js'
Copy the code

But now we pass in a variable called NODE_ENV on the command line, which can be distinguished in webpack.config.js.

Let’s create a configuration file called webpack.bine.js in the root directory:

webpack.combine.js:

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = env= > {
    return {
        entry: './src/index.js'.output: {
            filename: env.NODE_ENV === 'production' ? '[name].[hash].bundle.js' : '[name].bundle.js'.path: path.resolve(__dirname, 'dist')},plugins: [
            new CleanWebpackPlugin(),
            new HtmlWebpackPlugin({
                title: 'Merged into the same Webpack configuration'}}})]Copy the code

We can see ouput. Filename, which can be determined by NODE_ENV.

So I need to pass the parameters in package.json:

{" name ":" webpack - bundle ", "version" : "1.0.0", "description" : ""," main ":" index. Js ", "scripts" : {" test ": "echo \"Error: no test specified\" && exit 1", "start": "webpack-dev-server --open --config webpack.dev.js", "build": "webpack --config webpack.prod.js", "local": "webpack --env.custom=local --env.production=false --mode=development --progress --config webpack.local.js",+ "combine-dev": "webpack --env.NODE_ENV=development --config webpack.combine.js",
+ "combine-prod": "webpack --env.NODE_ENV=production --config webpack.combine.js"}, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "clean-webpack-plugin": "^ 3.0.0 HTML - webpack -", "plugins" : "^ 3.2.0", "lodash" : "^ 4.17.15", "uglifyjs - webpack - plugin" : "^ 2.2.0", "webpack" : "^ 4.41.5 webpack -", "cli" : "^ 3.3.10", "webpack - dev - server" : "^ 3.10.3", "webpack - merge" : "^ 4.2.2"}}Copy the code

Now execute the combine-dev and combine-prod separately, and you can see the different effects of the generated bundle.

The js file generated by combining-dev is main.bundle.js

Combine to prod the generated js file is the main a79eb0c94212b905d48b. Bundle. Js

But it is important to note that env.node_env is not process.env.node_env, so it does not change process.env.

That is, no matter how you generate the page, the process. Env.node_env that you get in the page is still production.

Section 2 Summary

  • Can be installedwebpack-mergeTools help us combine multiple configuration files into one
  • inwebpack.config.jsEnvironment variables cannot be obtainedprocess
  • Can be achieved bywebpack.DefinePluginPlug-ins help us modifyprocess.envThe value of the
  • You can also use the command lineCLIIn the--modeTo modify the mode of an environment variable
  • ifwebpack.config.jsThe output is a function, which allows us to use it on the command line--envPassing environment variables

Case address

Section 1: github.com/LinDaiDai/w…

Section two: github.com/LinDaiDai/w…

Note ⚠️ : in fact, “Lin Dull’s Webpack Road series” all textbook cases are the same project, but different branches can download separate cases, the main branch is all cases. Read README on Github for details.

Refer to the article

Knowledge is priceless, support original.

Reference article:

  • Webpack Chinese document

After the language

The guy who likes Lin Dull also hopes to follow Lin’s public account LinDaiDai or scan the following QR code πŸ‘‡πŸ‘‡πŸ‘‡.

I will update some front-end knowledge content and my original article πŸŽ‰ from time to time

Your encouragement is the main motivation for my continuous creation 😊.

Related recommendations:

The most detailed BPMN.js textbook in the whole Web

If you don’t understand Babel, I’ll send you a mask.

“[Suggested stars] To come to 45 Promise interview questions a cool end (1.1W words carefully arranged)”

“[suggestion πŸ‘] 40 more this interview questions sour cool continue (1.2W word by hand)”

“[why not three even] more simple than inheritance of JS inheritance – packaging (small test)”

【 Why not three times 】 finish these 48 questions to thoroughly understand JS inheritance (1.7W words including hot finishing – back to nature)

Data type conversion from 206 console.log()