webpack

官网:https://webpack.js.org/
英文官方文档:https://webpack.js.org/guides/
中文官方文档:https://www.webpackjs.com/guides/

1 简介

  • 分而治之是软件工程中的重要思想
  • 复杂的web系统:多功能、多页面、多状态、多系统
  • 模块化是目前前端最流行的分治手段

image.png

image.png

image.png

image.png

2 作用

image.png

  • 打包js,css,image,文件
  • 优化和压缩代码
  • 用户获取网站资源更快,体验更好

    3 Gulp和Webpack的比较

  • Gulp侧重于前端开发的整个过程的控制管理(像是流水线)

  • 给gulp配置不同的task(通过Gulp中的gulp.task()方法配置,比如启动 server、sass/less预编译、文件的合并压缩等等)来让gulp实现不同的功能,从而构建整个前端开发流程。
  • Webpack有人也称之为模块打包机,由此也可以看出Webpack更侧重于模块打包,当然我们可以把开发中的所有资源(图片、js文件、css文件等)都可以看成模块
  • 最初Webpack本身就是为前端JS代码打包而设计的,后来被扩展到其他资源的打包处理。Webpack是通过loader(加载器)和plugins(插件)对资源进行处理的。

    4 安装

    前提:node环境

    ★★★ 安装插件时,保证所有插件都使用nmp或者cnmp安装,不建议混着用,否则可能会出现意想不到的后果,例如依赖包明明已经安装但是因为安装工具的不同却识别不出。

进入工程文件夹,npm初始化

image.png

要安装最新版本或特定版本,请运行以下命令之一:

  1. npm install --save-dev webpack
  2. npm install --save-dev webpack@<version>

如果你使用 webpack 4+ 版本,你还需要安装 CLI。

  1. npm install --save-dev webpack-cli

★★★ 一步到位(推荐)
**

  1. npm install webpack webpack-cli --save-dev

5 起步与打包JS文件

5.1 创建目录结构、文件和内容

project
**

  1. webpack-demo
  2. |- package.json
  3. + |- index.html
  4. + |- /src
  5. + |- index.js

image.png

html.js

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

    // Lodash(目前通过一个 script 脚本引入)对于执行这一行是必需的
    element.innerHTML = _.join(['Hello', 'webpack', 'ZBW'], ' ');

    return element;
  }

document.body.appendChild(component());

index.html

<!doctype html>
<html>
  <head>
    <title>起步</title>
  </head>
  <body>
    <script src="./src/index.js"></script>
  </body>
</html>

还需要调整 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": {}
  }

5.2 安装lodash

要在 index.js 中打包 lodash 依赖,我们需要在本地安装 library:

在安装一个要打包到生产环境的安装包时,你应该使用 npm install --save,如果你在安装一个用于开发环境的安装包(例如,linter, 测试库等),你应该使用 npm install --save-dev

npm install --save lodash

5.3 调整目录结构

将“源”代码(/src)从我们的“分发”代码(/dist)中分离出来。“源”代码是用于书写和编辑的代码。“分发”代码是构建过程产生的代码最小化和优化后的“输出”目录,最终将在浏览器中加载:
project
**

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

调整代码
index.html

<!doctype html>
<html>
  <head>
    <title>起步</title>
  </head>
  <body>
    <script src="main.js"></script>
  </body>
</html>

html.js

import _ from 'lodash';  // 导入lodash

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

    // Lodash(目前通过一个 script 脚本引入)对于执行这一行是必需的
    element.innerHTML = _.join(['Hello', 'webpack', 'ZBW'], ' ');

    return element;
  }

  document.body.appendChild(component());

执行 npx webpack,会将我们的脚本作为入口起点,然后 输出main.js。Node 8.2+ 版本提供的 npx 命令,可以运行在初始安装的 webpack 包(package)的 webpack 二进制文件(./node_modules/.bin/webpack):

image.png

image.png

未使用配置文件时,默认将html.js打包为main.js文件,推荐使用下面介绍配置文件方式,可以自定义打包参数,另外出现的警告警告稍后处理。

5.4 使用配置文件

在 webpack 4 中,可以无须任何配置使用,然而大多数项目会需要很复杂的设置,这就是为什么 webpack 仍然要支持 配置文件。这比在终端(terminal)中手动输入大量命令要高效的多,所以让我们创建一个取代以上使用 CLI 选项方式的配置文件:

image.png

webpack.config.js

const path = require('path');  // 处理相关文件目录的操作

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

通过新配置文件再次执行构建

npx webpack --config webpack.config.js

image.png

image.png

bundle.js与之前main.js中内容是相同的,但是前者是使用自定义的配置文件进行打包,可以自定义相关

注意,当在 windows 中通过调用路径去调用 webpack 时,必须使用反斜线()。例如 node_modules\.bin\webpack --config webpack.config.js

5.5 去除警告

向配置文件中添加mode字段(development / production / none),即可消除警告
webpack.config.js

const path = require('path'); // 处理相关文件目录的操作

module.exports = {
    mode: 'development',
    entry: './src/index.js', // 入口
    output: {
        filename: 'bundle.js', // 出口
        path: path.resolve(__dirname, 'dist')
    }
};

image.png

5.6 自定义NPM脚本

考虑到用 CLI 这种方式来运行本地的 webpack 不是特别方便,我们可以设置一个快捷方式。在 package.json 添加一个npm 脚本(npm script)
webpack.config.js

{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "npx webpack --config webpack.config.js"  // 此处为自定义快捷命令的脚本,复制时请删除该注释
  },
  "author": "ZBW",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.32.2",
    "webpack-cli": "^3.3.2"
  },
  "dependencies": {
    "lodash": "^4.17.11"
  }
}

使用自定义快捷方式

image.png

6 与Sass结合,打包CSS

上面介绍了打包js文件,本章介绍如何结合sass,打包css文件。

6.1 安装插件

css-loader 加载css的插件
style-loader 将css文件插入至html文件中的插件
sass sass插件
sass-loader 能将sass文件插入至html文件中的插件
extract-text-webpack-plugin 能够提取sass文件中的文本,需安装4.x版本,否则下面程序会报错
node-sass 很多插件都会依赖该插件

★★★ 安装插件时,保证所有插件都使用nmp或者cnmp安装,不建议混着用,否则可能会出现意想不到的后果,例如依赖包明明已经安装但是因为安装工具的不同却识别不出。

cnpm install css-loader style-loader sass sass-loader  --save-dev

image.png

cnpm install extract-text-webpack-plugin@next --save-dev

image.png

cnpm install node-sass --save-dev

image.png

6.2 修改配置文件

const path = require('path'); // 处理相关文件目录的操作
const ExtractTextPlugin = require('extract-text-webpack-plugin');  // 提取scss文件内容的插件

module.exports = {
    mode: 'development',
    entry: './src/index.js', // 入口
    output: {
        filename: 'bundle.js', // 出口
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        // 定义一些规则,让webpack能够处理scss文件
        rules: [
            {
                // 匹配 .scss文件
                test: /\.scss$/,  
                use: ExtractTextPlugin.extract({
                    // 解析完scss文件后用style方式添加至html文件中的方式
                    fallback: 'style-loader', 
                    // 使用什么工具去 加载/解析 scss文件
                    use: ['css-loader', 'sass-loader']  
                })
            }
        ]
    },
    plugins: [
        // 自定义生成css文件的名称
        new ExtractTextPlugin({
            filename: 'style.css' 
        }) 
    ]
};

6.3 代码展示

index.scss
**

@charset 'UTF-8';


$important_color: red;
$soso_color: blue;
$border: 2px solid gold;
$mb10: 10px;
$mb20: 20px;

.todo {
    border: $border;

    p {
        color: $important_color;
        margin-bottom: $mb20;
    }

    li {
        margin-bottom: $mb10;
        &.important {
            color: $important_color;
        }

        &.soso {
            color: $soso_color;
        }
    }
}

index.js

index.js 中需要导入index.scss文件,因为在配置文件 webpack.config.js 中只设置了一入口,即该js文件,如想对scss文件进行操作(转换并打包),需要再js文件中导入scss文件。

import _ from 'lodash';  // 导入lodash
import './index.scss'

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

    // Lodash(目前通过一个 script 脚本引入)对于执行这一行是必需的
    element.innerHTML = _.join(['Hello', 'webpack', 'ZBW'], ' ');

    return element;
  }

  document.body.appendChild(component());

index.html

需将打包完成后的css文件引入即可。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="style.css">
  <title>webpack-demo</title>
</head>

<body>
  <div class="todo">
    <p>今天要做的事情:</p>
    <li class="important">11</li>
    <li class="important">22</li>
    <li class="soso">33</li>
    <li class="soso">44</li>
    <li class="important">55</li>
  </div>

  <script src="bundle.js"></script>
</body>

</html>

6.4 运行结果

执行自定义脚本命令

npm run build

image.png

image.png

image.png

7 将CSS文件打包至JS文件中(单页面应用)

使用webpack将CSS文件打包至JS文件中,在HTML文件中只需导入JS文件即可加载所有样式。

7.1 代码处理

插件:同上,extract-text-webpack-plugin除外。
将HTML文件中引入CSS文件注释,刷新页面会发现所有样式全部消失;JS文件同上,需引入SCSS文件

<!-- <link rel="stylesheet" href="style.css"> -->

7.2 修改配置文件

const path = require('path'); // 处理相关文件目录的操作

module.exports = {
    mode: 'development',
    entry: './src/index.js', // 入口
    output: {
        filename: 'bundle.js', // 出口
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        // 定义一些规则,让webpack能够处理scss文件
        rules: [
            {
                // 匹配 .scss文件
                test: /\.scss$/,

                // 从右向左依次进行处理
                use: ['style-loader', 'css-loader', 'sass-loader']
            }
        ]
    }
};

7.3 运行结果

执行自定义脚本命令

npm run build

image.png

image.png

与上面显示效果相同

image.png

8 打包多个JS文件

8.1 新增代码

about.html
**

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>webpack-about</title>
</head>

<body>
    <h1>这里是about页面</h1>

    <h2>公司介绍</h2>
    <p>华中测评中心</p>
    <p>华中测评中心华中测评中心华中测评中心华中测评中心华中测评中心华中测评中心华中测评中心华中测评中心华中测评中心</p>

    <hr>

    <h2>网站介绍</h2>
    <p>门户网站</p>
    <p>门户网站门户网站门户网站门户网站门户网站门户网站门户网站门户网站门户网站门户网站门户网站门户网站门户网站门户网站门户网站门户网站门户网站</p>

    <script src="about.bundle.js"></script>
</body>

</html>

about.js

alert('这里是about页面!')

index.html
新增:

<a  href="about.html">关于</a>

修改:

<script src="bundle.js"></script>

=>

<script src="home.bundle.js"></script>

8.2 修改配置文件

const path = require('path'); // 处理相关文件目录的操作
const ExtractTextPlugin = require('extract-text-webpack-plugin');  // 提取scss文件内容的插件

module.exports = {
    mode: 'development',

    // 配置多个入口
    entry: {
        home: './src/index.js',
        about: './src/about.js',
    },

    output: {
        filename: '[name].bundle.js', // 出口,生成多个js文件,名称:[key_name].bundle.js
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        // 定义一些规则,让webpack能够处理scss文件
        rules: [
            {
                // 匹配 .scss文件
                test: /\.scss$/,

                // 从右向左依次进行处理
                use: ['style-loader', 'css-loader', 'sass-loader']
            }
        ]
    }

8.3 运行结果

执行自定义脚本命令

npm run build

image.png

image.png

image.png


点击“关于”
image.png

9 打包多个SCSS(CSS)文件

此处时打包多个scss文件,并合并为对应的js文件中,如不想合并,则按照上面打包CSS文件,修改配置文件即可。

9.1 新增代码

about.scss
**

@charset 'UTF-8';


$size10: 10px;
$size20: 20px;
$size50: 50px;
$title-color: red;
$para-color: blue;
$border: 1px solid green;
$bg-color: gray;

h1 {
    font-size: $size50;
    color: $title-color;
}

h2 {
    font-size: $size20;
    background-color: $bg-color;
}

p {
    font-size: $size10;
    border: $border;
}

about.js
入口原因,导入scss文件

import './about.scss';

alert('这里是about页面!')

配置文件同上,不用修改

9.2 运行结果

执行自定义脚本命令

npm run build

image.png

image.png
点击“关于”
image.png

10 设置监听状态

10.1 使用 watch

webpack也可以设置监听状态,到配置文件中的入口文件发生改变时,会自动按照配置文件进行打包,无需重复执行命令。

npx webpack --watch

image.png

10.2 使用开发者服务器方式(推荐)

插件安装:
webpack-dev-server: 启动本地的webpack服务

cnpm install webpack-dev-server --save-dev

image.png

修改配置文件:

const path = require('path'); // 处理相关文件目录的操作
const ExtractTextPlugin = require('extract-text-webpack-plugin');  // 提取scss文件内容的插件

module.exports = {
    mode: 'development',

    // 配置多个入口
    entry: {
        home: './src/index.js',
        about: './src/about.js',
    },

    output: {
        filename: '[name].bundle.js', // 出口,生成多个js文件,名称:[key_name].bundle.js
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        // 定义一些规则,让webpack能够处理scss文件
        rules: [
            {
                // 匹配 .scss文件
                test: /\.scss$/,

                // 从右向左依次进行处理
                use: ['style-loader', 'css-loader', 'sass-loader']
            }
        ]
    },
    // 设置webpack服务端
    devServer: {
        // 设置监听路径
        contentBase: path.join(__dirname, 'dist'),
        // 主机
        host: 'localhost',
        // 端口
        port: 8888,
    }
};

启动服务:
**

npx webpack-dev-server --config webpack.config.js

或者(颜色区分,进度,热加载方式)(推荐)

npx webpack-dev-server --config webpack.config.js --color --progress --hot

image.png

打开浏览器输入:http://localhost:8888/
image.png

当入口文件发生改变时,会按照配置文件自动进行修改并打包。
命令太长?自定义脚本命令试试吧
package.json

{
 "name": "webpack-demo2",
 "version": "1.0.0",
 "description": "",
 "main": "webpack.config.js",
 "dependencies": {
   "lodash": "^4.17.11"
 },
 "devDependencies": {
   "css-loader": "^2.1.1",
   "extract-text-webpack-plugin": "^4.0.0-beta.0",
   "node-sass": "^4.12.0",
   "sass": "^1.20.3",
   "sass-loader": "^7.1.0",
   "style-loader": "^0.23.1",
   "webpack": "^4.32.2",
   "webpack-cli": "^3.3.2",
   "webpack-dev-server": "^3.5.1"
 },
 "scripts": {
   "test": "echo \"Error: no test specified\" && exit 1",
   "build": "npx webpack --config webpack.config.js",
   "start": "npx webpack-dev-server --config webpack.config.js --color --progress --hot"
 },
 "author": "ZBW",
 "license": "ISC"
}

执行自定义脚本命令

npm run start

image.png

11 参考