Webpack 4 新手入门教程,全面讲解

什么是webpack?

说白了webpack只是一个打包工具,在webpack之前就已经有很多打包工具了,比如Gulp,webpack是基于node开发出来的, 因此只能在node环境下运行webpack

本教程主要讲解webpack基本的功能使用,基本是按照官网教程讲解,只是对官网教程做了整合及部分修改处理:

  • webpack 环境安装
  • 创建项目
  • 管理资源
  • 管理输出
  • 开发环境配置
  • 模块热替换
  • 生产环境配置
  • 代码分离
  • 缓存
    本教程基本按以上功能讲解

本教程环境依赖版本为:webpack 4.43.0(目前最新版本)

一.webpack 环境安装

  • 本地安装
npm install --save-dev webpack
npm install --save-dev webpack-cli
  • 全局安装
npm install --global webpack

官方不推荐全局安装 webpack。这会将你项目中的 webpack 锁定到指定版本,并且在使用不同的 webpack 版本的项目中,可能会导致构建失败。

查看webpack版本号

webpack -V

如果安装成功则会显示版本号 如:

Version: webpack 4.43.0

二.创建项目

  • 创建文件夹webpack-demo,并在终端打开
    运行如下命令行:
npm init -y
npm install webpack webpack-cli --save-dev

安装成功后项目结构如下:


image.png
  • 新增文件如下 ( 注意:本文中 +号表示 添加,-号表示删除
  webpack_demo
  |- package.json
+ |- index.html
+ |- /src
+   |- index.js
image.png
  • 添加刚刚新增的文件内容
    src/index.js
function component() {
  var element = document.createElement('div');

  // Lodash 只是一个js的插件 优化了很多原生js的写法 下面的 _join 可以理解成 原生js里array的 join 方法  webpack 是依赖于Lodash这个插件的
  element.innerHTML = _.join(['Hello', 'webpack'], ' ');

  return element;
}

document.body.appendChild(component());

index.html

<!doctype html>
<html>
  <head>
    <title>起步</title>
    <script src="https://unpkg.com/lodash@4.16.6"></script>
  </head>
  <body>
    <script src="./src/index.js"></script>
  </body>
</html>

调整 package.json 文件
我们还需要调整 package.json 文件,以便确保我们安装包是私有的(private),并且移除 main 入口。这可以防止意外发布你的代码。

{
    "name": "webpack-demo",
    "version": "1.0.0",
    "description": "",
+   "private": true,//新增-------------------
-   "main": "index.js",//删除--------------------------
    "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
      "webpack": "^4.0.1",
      "webpack-cli": "^2.0.9"
    },
    "dependencies": {}
  }
  • 在浏览器运行 index.html 就会看到 Hello webpack 这句话了
    image.png
  • 创建一个 dist 文件夹

dist 文件夹就是我们的生产包,就是可以发布到线上的代码

调整项目结构,把index.html文件丢到dist里面

webpack_demo
  |- package.json
+ |- /dist
+   |- index.html
- |- index.html
  |- /src
    |- index.js

然后用npm 的方式安装lodash 依赖(之前是直接引入的 src 地址文件)

npm install --save lodash

在src/index.js 引入 lodash

+ import _ from 'lodash';//增加  用import 方式引入
  function component() {
    var element = document.createElement('div');
  // Lodash用import 方式引入
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
    return element;
  }
  document.body.appendChild(component());

同时删除dist/index.html文件里面的之前 引入lodash的地址,并添加<script src="main.js"></script>

<!doctype html>
<html>
  <head>
    <title>起步</title>
    <!-- <script src="https://unpkg.com/lodash@4.16.6"></script> -->
  </head>
  <body>
    <!-- <script src="./src/index.js"></script> -->
    <!-- 注意:现在目录里是没有main.js 文件,先这样引进来 -->
    <script src="main.js"></script>
  </body>
</html>

执行 npx webpack

Node 8.2+ 版本提供的 npx 命令,可以打包webpack 文件(注意: 是npx不是 npm

E:\testItem\webpack_demo> npx webpack
Hash: 8747c90e1866f21be58c
Version: webpack 4.43.0
Time: 2236ms
Built at: 2020-05-19 9:35:46 PM
  Asset      Size  Chunks             Chunk Names
main.js  72.1 KiB       0  [emitted]  main
Entrypoint main = main.js
[1] ./src/index.js 282 bytes {0} [built]
[2] (webpack)/buildin/global.js 472 bytes {0} [built]
[3] (webpack)/buildin/module.js 497 bytes {0} [built]
    + 1 hidden module

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

打包成功后dist文件夹自动生成main.js文件,
在浏览器中打开 dist/index.html,可正常显示Hello webpack'。


image.png

image.png
创建配置文件

创建配置文件可以按项目需自定义一些规则

 webpack-demo
  |- package.json
+ |- webpack.config.js //增加配置文件
  |- /dist
      index.html
 -    main.js  //删除main.js
  .......//其他文件

webpack.config.js 添加内容

const path = require('path');//引入路径内置依赖  不用单独安装

module.exports = {
  entry: './src/index.js',//表示入口文件
  output: {
    filename: 'bundle.js', //打包后输出文件名称
    path: path.resolve(__dirname, 'dist') //输出目录文件夹(dist)
  }
};

修改 dist/index.html 引入文件 bundle.js

<!doctype html>
<html>
  <head>
    <title>起步</title>
  </head>
  <body>
    <!-- 引入bundle.js -->
    <script src="bundle.js"></script>
  </body>
</html>

现在文件结构如下


image.png

运行 npx webpack --config webpack.config.js

E:\testItem\webpack_demo> npx webpack --config webpack.config.js
Hash: 8f98a49ae24fdf34e9d8
Version: webpack 4.43.0
Time: 369ms
Built at: 2020-05-19 10:12:29 PM
    Asset      Size  Chunks             Chunk Names
bundle.js  72.1 KiB       0  [emitted]  main
Entrypoint main = bundle.js
[1] ./src/index.js 282 bytes {0} [built]
[2] (webpack)/buildin/global.js 472 bytes {0} [built]
[3] (webpack)/buildin/module.js 497 bytes {0} [built]
    + 1 hidden module

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

在浏览器中打开 dist/index.html,可正常显示Hello webpack'

添加npm 打包方式 "build": "webpack"
  {
    "name": "webpack-demo",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1",
+     "build": "webpack"  //添加代码
    },
    "keywords": [],
    ......其他代码
  }

使用 npm run build 命令

 E:\testItem\webpack_demo> npm run build

> webpack_demo@1.0.0 build E:\testItem\webpack_demo
> webpack

Hash: 8f98a49ae24fdf34e9d8
Version: webpack 4.43.0
Time: 393ms
Built at: 2020-05-19 10:31:44 PM
    Asset      Size  Chunks             Chunk Names
bundle.js  72.1 KiB       0  [emitted]  main
Entrypoint main = bundle.js
[1] ./src/index.js 282 bytes {0} [built]
[2] (webpack)/buildin/global.js 472 bytes {0} [built]
[3] (webpack)/buildin/module.js 497 bytes {0} [built]
    + 1 hidden module

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

npm 打包完毕后也能正常运行

三、管理资源

本小节主要讲解加载css、image

加载 CSS

先安装2个css依赖

npm install --save-dev style-loader css-loader

webpack.config.js 添加依赖

 const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    },
+   module: { //这里是依赖包,所有依赖包都件放在这里面
+     rules: [
+       {
+         test: /\.css$/,//这里是正则 查找 css文件
+         use: [
+           'style-loader',//css依赖的包
+           'css-loader'//css依赖的包
+         ]
+       }
+     ]
+   }
  };
  • 添加样式文件
    src/style.css
webpack_demo
  |- package.json
  |- webpack.config.js
  |- /dist
    |- bundle.js
    |- index.html
  |- /src
+   |- style.css //添加的文件
    |- index.js
  |- /node_modules

src/style.css

.hello {
  color: red;
}
  • 引入 style.css 文件
    src/index.js
import _ from 'lodash';
+ import './style.css'; //添加的文件

function component() {
    var element = document.createElement('div');

    // 用npm的方式引入 lodash 插件
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
+   element.classList.add('hello');//添加一个类名
    return element;
}

document.body.appendChild(component());

运行npm run build

 E:\testItem\webpack_demo> npm run build

> webpack_demo@1.0.0 build E:\testItem\webpack_demo
> webpack

Hash: 36587c29888aada8451a
Version: webpack 4.43.0
Time: 3102ms
Built at: 2020-05-20 10:13:50 PM
    Asset      Size  Chunks             Chunk Names
bundle.js  75.8 KiB       0  [emitted]  main
Entrypoint main = bundle.js
[1] ./src/index.js 338 bytes {0} [built]
[2] (webpack)/buildin/global.js 472 bytes {0} [built]
[3] (webpack)/buildin/module.js 497 bytes {0} [built]
[4] ./src/style.css 519 bytes {0} [built]
[6] ./node_modules/css-loader/dist/cjs.js!./src/style.css 264 bytes {0} [built]
    + 3 hidden modules

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

浏览器后台查看变化


image.png
加载图片
  • 常用于样式background图片显示等
    先安装文件依赖包
npm install --save-dev file-loader

webpack.config.js

const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            'style-loader',
            'css-loader'
          ]
        },
+       {
+         test: /\.(png|svg|jpg|gif)$/,
+         use: [
+           'file-loader'
+         ]
+       }
      ]
    }
  };

添加一个图片


image.png

src/index.js 引入图片

import _ from 'lodash';
import './style.css';
+ import Icon from './icon.png';//引入图片

function component() {
    var element = document.createElement('div');

    // 用npm的方式引入 lodash 插件
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
    element.classList.add('hello');
    // 将图像添加到我们现有的 div。
    + var myIcon = new Image(); //添加图片
    + myIcon.src = Icon;
    + element.appendChild(myIcon);
    return element;
}

document.body.appendChild(component());

src/style.css

  .hello {
    color: red;
+   background: url('./icon.png'); //背景图片
  }

运行npm run build 后打开 dist/index.html 文件 查看变化


image.png
image.png
加载数据

数据文件有的是内置的,直接引用即可,如JSON文件,如果要引入比如XML这样的文件,就要用到对应的依赖包

npm install --save-dev xml-loader

webpack.config.js


  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            'style-loader',
            'css-loader'
          ]
        },
        {
          test: /\.(png|svg|jpg|gif)$/,
          use: [
            'file-loader'
          ]
        },
+       {
+         test: /\.xml$/,//新加文件
+         use: [
+           'xml-loader'
+         ]
+       }
      ]
    }
  };

src 下添加data.xml 文件 并加入内容
src/data.xml

<?xml version="1.0" encoding="UTF-8"?>
<note>
  <to>Mary</to>
  <from>John</from>
  <heading>Reminder</heading>
  <body>Call Cindy on Tuesday</body>
</note>

src/index.js 引入data.xml

import _ from 'lodash';
import './style.css';
import Icon from './icon.png';
+ import Data from './data.xml';//引入
function component() {
    var element = document.createElement('div');

    // 用npm的方式引入 lodash 插件
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
    element.classList.add('hello');
    // 将图像添加到我们现有的 div。
    var myIcon = new Image();
    myIcon.src = Icon;

    element.appendChild(myIcon);
  + console.log("data",Data);//打印XML数据
    return element;
}

document.body.appendChild(component());

npm run build后 运行浏览器打印数据


image.png

四、管理输出

自动配置 dist/index.html 文件里的引用
src目录下新建 print.js 文件夹
src/print.js 添加内容

export default function printMe() {
    console.log('我是 print.js 里面的类容');
  }

并且在 src/index.js 引入

import _ from 'lodash';
import './style.css';
import Icon from './icon.png';
import Data from './data.xml';
+ import printMe from './print.js';

function component() {
    var element = document.createElement('div');

    // 用npm的方式引入 lodash 插件
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
    element.classList.add('hello');
    // 将图像添加到我们现有的 div。
    var myIcon = new Image();
    myIcon.src = Icon;

    element.appendChild(myIcon);
    console.log("data", Data);

+    var btn = document.createElement('button');
+    btn.innerHTML = 'Click me and check the console!';
+    btn.onclick = printMe;
+    element.appendChild(btn);
    return element;
}

document.body.appendChild(component());

更新 dist/index.html 文件

<!doctype html>
<html>
  <head>
    <title>起步</title>
+    <script src="./print.bundle.js"></script>
  </head>
  <body>
    <!-- 引入bundle.js -->
-     <!-- <script src="bundle.js"></script> -->
+    <script src="./app.bundle.js"></script>
  </body>
</html>

webpack.config.js 调整入口文件 跟输出文件

const path = require('path');

module.exports = {
    // entry: './src/index.js',
    entry: {
+       app: './src/index.js',
+       print: './src/print.js'
    },
    output: {
        // filename: 'bundle.js',
+       filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    module: {
........其他文件
    }

运行 npm run build,dist文件夹会自动生成 app.bundle.js 跟 print.bundle.js


image.png

浏览器运行 dist/index.html


image.png
html-webpack-plugin 插件使用

在上一小节中如果我们更改了其中一个入口起点的名称或者更改新的名称后,dist/index.html 并不会自动跟新,因此我们可以用html-webpack-plugin 插件来解决这个问题

  • 安装
npm install --save-dev html-webpack-plugin
  • webpack.config.js 调整
const path = require('path');
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    // entry: './src/index.js',
    entry: {
        app: './src/index.js',
        print: './src/print.js'
    },
    output: {
        // filename: 'bundle.js',
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
 +   plugins: [ //这里是放插件的地方
 +       new HtmlWebpackPlugin({
 +           title: '我是新的index标题'
 +       })
 +   ],
    module: { //这里放依赖包的地方
    ....//其他代码
  • 执行 npm run build 后会发现 dist/index.html文件类容已经跟新
image.png
自动清理dist文件

现在每次运行npm run build 重新打包后,只会添加新的包,之前dist下一些无用的老包还存在,可使用 clean-webpack-plugin 插件清理

  • 安装
npm install clean-webpack-plugin --save-dev
  • webpack.config.js 跟新代码
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
+ const { CleanWebpackPlugin } = require("clean-webpack-plugin")  //注意  这里是最新的引入方式 可能跟其他老版的引入不一样
module.exports = {
    // entry: './src/index.js',
    entry: {
        app: './src/index.js',
        print: './src/print.js'
    },
    output: {
        // filename: 'bundle.js',
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    plugins: [
+       new CleanWebpackPlugin(),//注意 要放到 其他插件的上面,表示一开始就把文件清理干净
        new HtmlWebpackPlugin({
            title: '我是新的index标题'
        })
    ],
    module: {
...//其他代码

运行npm run build之前 可在dist 文件夹下添加一个无用的文件(随意),然后在重新打包,可发现之前那些无用的文件都清除掉了

五、开发环境配置

当 webpack 打包源代码时,可能会很难追踪到错误和警告在源代码中的原始位置。例如,如果将三个源文件(a.js, b.js 和 c.js)打包到一个 bundle(bundle.js)中,而其中一个源文件包含一个错误,那么堆栈跟踪就会简单地指向到 bundle.js。这并通常没有太多帮助,因为你可能需要准确地知道错误来自于哪个源文件。

代码报错位置查询
  • 在src/print.js 文件中生成一个错误
export default function printMe() {
    // console.log('我是 print.js 里面的类容');
    console.error('我是 print.js 里面的类容---并报了个错');
  }
  • 重新npm run build 打包,运行浏览器点击按钮


    image.png

    image.png

    此时发现这个报错文件是我们打包好的app.bundle.js文件,并不是源文件print.js,而且代码已混淆,看不出来本身报错的地方,没有参考价值,因此要改进

  • 添加报错工具
    webpack.config.js 代码添加工具
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require("clean-webpack-plugin")
module.exports = {
    // entry: './src/index.js',
    entry: {
        app: './src/index.js',
        print: './src/print.js'
    },
    output: {
        // filename: 'bundle.js',
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
+    devtool: 'inline-source-map',//wabpack 内置工具  不需要npm安装
    plugins: [

重新打包-并查看报错源代码-已经完全显示本来的print.js文件及代码


image.png
热更新

之前我们想要预览修改后的代码效果,需要手动打包项目,并且要刷新浏览,这样很不方便,使用webpack-dev-server可用于开发环境,实时更新代码

  • 安装
npm install --save-dev webpack-dev-server
  • webpack.config.js 修改
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const {
    CleanWebpackPlugin
} = require("clean-webpack-plugin")
module.exports = {
    // entry: './src/index.js',
    entry: {
        app: './src/index.js',
        print: './src/print.js'
    },
    output: {
        // filename: 'bundle.js',
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    devtool: 'inline-source-map',
 +   devServer: {
 +      contentBase: './dist'
 +   },
    plugins: [
...//其他代码
  • package.json 添加配置
{
  "name": "webpack_demo",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
+   "start": "webpack-dev-server --open"
  },
  "keywords": [],
  "author": "",
...//其他代码

运行npm run start 会生成一个本地服务器地址http://localhost:8080/,运行http://localhost:8080/后这样浏览器就能实时刷新修改的代码了,不需要手动操作了

E:\testItem\webpack_demo> npm run start

> webpack_demo@1.0.0 start E:\testItem\webpack_demo
> webpack-dev-server --open

i 「wds」: Project is running at http://localhost:8080/
i 「wds」: webpack output is served from /
i 「wds」: Content not from webpack is served from ./dist
i 「wdm」: wait until bundle finished: /
i 「wdm」: Hash: 862425721897c85f3b10
image.png

六、模块热替换

官网解释:模块热替换(hot module replacement 或 HMR)是 webpack 提供的最有用的功能之一。它允许在运行时更新所有类型的模块,而无需完全刷新

启用 HMR
  • webpack.config.js 更新
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const {
    CleanWebpackPlugin
} = require("clean-webpack-plugin")
+ const webpack = require('webpack');//HMR  是webpack 内置的依赖包
module.exports = {
    // entry: './src/index.js',
    entry: {
   -       // app: './src/index.js',
   -        // print: './src/print.js'
   +   app: './src/index.js' //变成一个入口文件
    },
    output: {
        // filename: 'bundle.js',
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    devtool: 'inline-source-map',
    devServer: {
        contentBase: './dist',
   +    hot: true
    },
    plugins: [
        new CleanWebpackPlugin(), //注意 要放到 其他插件的上面,表示一开始就把文件清理干净
        new HtmlWebpackPlugin({
            title: '我是新的index标题'
        }),
  +     new webpack.HotModuleReplacementPlugin()//HMR  是webpack 内置的依赖包
    ],
    module: {
  • 修改 src/index.js 文件
 ...//之前的代码  
  document.body.appendChild(component());
+ if (module.hot) {
+   module.hot.accept('./print.js', function() {
+     console.log('Accepting the updated printMe module!');
+     printMe();
+   })
+ }
  • npm run start 运行后 修改print.js 里面的打印类容
export default function printMe() {
    console.log('我是 print.js 里面的类容11122333');
    // console.error('我是 print.js 里面的类容---并报了个错');
  }

我们发现只要已更改 print.js里面的类容 index.js里面就能监控到代码更新


image.png

但是 我们点击按钮时还是打印的更改前的类容


image.png
  • 继续修改代码 src/index.js
import _ from 'lodash';
import './style.css';
import Icon from './icon.png';
import Data from './data.xml';
import printMe from './print.js';

function component() {
    var element = document.createElement('div');

    // 用npm的方式引入 lodash 插件
    element.innerHTML = _.join(['Hello', 'webpack1111111'], '');
    element.classList.add('hello');
    // 将图像添加到我们现有的 div。
    var myIcon = new Image();
    myIcon.src = Icon;

    element.appendChild(myIcon);
    console.log("data", Data);

    var btn = document.createElement('button');
    btn.innerHTML = 'Click me and check the console!';
    btn.onclick = printMe;
    element.appendChild(btn);
    return element;
}

- // document.body.appendChild(component());
+ let element = component(); // 存储 element,以在  print.js 修改时重新渲染
+ document.body.appendChild(element);
if (module.hot) {
    module.hot.accept('./print.js', function () {
        console.log('print.js模块发生了变化');
 -       // printMe();
 +      document.body.removeChild(element);
 +       element = component(); // Re-render the "component" to update the click handler
 +       element = component(); // 重新渲染 "component",以便更新 click 事件处理函数
 +       document.body.appendChild(element);
    })
}

这样就实现了整个模块自动刷新了(包括修改style.css 文件)

七、生成环境配置

因为生成环境跟开发环境用的插件跟依赖有的地方是不同的,因此分开设置会跟好

  • 安装
npm install --save-dev webpack-merge
  • 添加文件(3个)
  webpack_demo
  |- package.json
  webpack.config.js //这里的配置文件不会再使用
+ webpack.common.js //方通用代码的地方
+ webpack.dev.js //开发配置文件
+ webpack.prod.js //生成配置文件
   /dist
   /src
    index.js
  • webpack.common.js
 const path = require('path');
 const {
     CleanWebpackPlugin
 } = require("clean-webpack-plugin")
 const HtmlWebpackPlugin = require('html-webpack-plugin');

 module.exports = {
     entry: {
         app: './src/index.js'
     },
     plugins: [
         new CleanWebpackPlugin(),
         new HtmlWebpackPlugin({
             title: 'Production'
         })
     ],
     output: {
         filename: '[name].bundle.js',
         path: path.resolve(__dirname, 'dist')
     },
     module: {
         rules: [{
                 test: /\.css$/,
                 use: [
                     'style-loader',
                     'css-loader'
                 ]
             },
             {
                 test: /\.(png|svg|jpg|gif)$/,
                 use: [
                     'file-loader'
                 ]
             },
             {
                 test: /\.xml$/,
                 use: [
                     'xml-loader'
                 ]
             }
         ]
     },
 };
  • webpack.dev.js
 const merge = require('webpack-merge');
 const common = require('./webpack.common.js');

 module.exports = merge(common, {
   mode: 'development',
   devtool: 'inline-source-map',
   devServer: {
     contentBase: './dist'
   }
 });
  • webpack.prod.js
 const merge = require('webpack-merge');
 const common = require('./webpack.common.js');

 module.exports = merge(common, {
   mode: 'production',
 });
  • package.json 配置启动项
{
  "name": "webpack_demo",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "//build": "webpack",  //可删除
  +  "build": "webpack --config webpack.prod.js",
    "//start": "webpack-dev-server --open",//可删除
  +  "start": "webpack-dev-server --open --config webpack.dev.js"
  },
  "keywords": [],
...//下面的其他代码

运行 npm run start 跟 npm run build 都可正常运行项目

开发or生成环境判断

使用 process.env.NODE_ENV 即可判断,从 webpack v4 开始, 指定 mode会自动地配置

  • src/index.js 添加代码
if (process.env.NODE_ENV !== 'production') {
    console.log('当前是开发环境');
}else{
    console.log('当前是生成环境');
}
image.png

八、代码分离

代码分离可以打包多个js文件,这样可实现按需加载效果,之前我们只生成了一个app.bundle.js文件,接下来我们实现打包成多个文件

分离
  • 添加一个文件
    src/another-module.js
import _ from 'lodash';//这里其实已经是重复引入了lodash依赖,index.js里面也引入了,后续会解决这个问题

console.log(
  _.join(['其他', '模块', '加载了!'], ' ')
);
  • webpack.common.js 调整
 const path = require('path');
 const {
     CleanWebpackPlugin
 } = require("clean-webpack-plugin")
 const HtmlWebpackPlugin = require('html-webpack-plugin');

 module.exports = {
     entry: {
         app: './src/index.js',
+        another: './src/another-module.js'//添加入口文件
     },
+    optimization: {//防止重复代码处理
+        splitChunks: {
+            chunks: 'all'
+         }
+     },
     plugins: [

npm run build 打包后生成单独的another-module.js 文件


image.png

懒加载

懒加载的意思就是说项目初始化的时候,如果没有用到的页面就不请求,只有当需要用的时候才会去请求加载代码

  • 修改src/print.js 内容
console.log('print.js 模块已经加载! 请查看浏览器后台 network tab 工具');

export default () => {
  console.log('点击了按钮');//目的是只有点击了按钮print.js 这个模块才加载
};
  • src/index.js 代码

webpack webpack 提供了两个类似的技术。第一种,也是推荐选择的方式是,使用符合 ECMAScript 提案import() 语法 来实现动态导入。第二种,则是 webpack 的遗留功能,使用 webpack 特定的 require.ensure。让我们先尝试使用第一种

//懒加载----------------
 import _ from 'lodash';

 function component() {
    var element = document.createElement('div');
   var button = document.createElement('button');
   var br = document.createElement('br');

   button.innerHTML = 'Click me and look at the console!';
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
   element.appendChild(br);
   element.appendChild(button);


   button.onclick = e => import(/* webpackChunkName: "print" */ './print').then(module => {
     var print = module.default;

     print();
   });

    return element;
  }
 document.body.appendChild(component());
image.png

image.png

九、缓存

缓存的目的就是每次打包跟新后没有变化的代码不会请求新的资源,服务器端还是加载老的代码,这样可以节省服务器开销,为了识别新老代码是否有变化,可以给打包好的文件后缀添加hash值

  • webpack.common.js 修改
 const path = require('path');
 const {
     CleanWebpackPlugin
 } = require("clean-webpack-plugin")
 const HtmlWebpackPlugin = require('html-webpack-plugin');

 module.exports = {
     entry: {
         app: './src/index.js',
         another: './src/another-module.js'//添加入口文件
     },
     plugins: [
         new CleanWebpackPlugin(),
         new HtmlWebpackPlugin({
             title: 'Production'
         })
     ],
     output: {
        //  filename: '[name].bundle.js',//这里的后缀名是写死的
+      filename: '[name].[contenthash].js',//后缀名添加哈希值
        path: path.resolve(__dirname, 'dist')
     },
...//其他代码

打包代码后生成哈希值文件,如果文件类容没变再次打包的话,文件名不会有任何变化


image.png

十、入门篇完结--

到目前为止,wabpack基本操作已基本涉及,再会!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335