Webpack:从入门到配置、懒加载

869 阅读3分钟

文档

Webpack 用于编译JS模块,即俗称的“项目工程化”工具。

详见英文文档中文文档

安装

如果你使用脚手架(vue-cli)等快速搭建工具,一般都集成了Webpack和一些基本配置。

版本信息

首先通过 npm 查看 Webpack 的版本信息。

$ npm info webpack

// webpack@4.41.2 | MIT | deps: 23 | versions: 625

// 可执行文件
// bin: webpack

// 所有版本
// dist-tags:
// latest: 4.41.2   legacy: 1.15.0   next: 5.0.0-beta.9
// webpack-2: 2.7.0   webpack-3: 3.12.0

我们使用默认的最新版本 webpack4。这里推荐使用 yarn 代替 npm。

启动 Webpack

使用本地路径

本地启动:

$ ./node_modules/.bin/webpack

使用 npx 命令

使用 npx 来启动 Webpack,会自动在当面目录寻找可执行的文件。

注意: 在 windows 系统中某些情况可能存在不稳定性,比如安装 node 时的路径有空格等。

$ npx webpack

Webpack 默认在当前目录的 dist 目录中输出结果。这是通过集成的加载器 babel-loader 实现的。

优化生成方式(build)

使用快速脚本,每次构建时清空 dist 目录并重新生成。

Mac/Linux

{
   "script": {
     "build": "rm -rf dist; webpack"
   }
}

Windows

{
   "script": {
     "build": "rm -rf dist && webpack"
   }
}

使用命令

$ yarn build

使用插件

使用插件 clean-webpack-plugin 来代替清理工作。

安装:

$ yarn add clean-webpack-plugin

配置插件:

const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
    entry: {
      app: './src/index.js',
      print: './src/main.js'
    },
    plugins: [
      new CleanWebpackPlugin(['dist'])
    ]
  };
}

常用配置

默认会警告设置配置文件中的转译模式。

路径和模式

创建配置文件。

$ touch webpack.config.js

配置:

const path = require("path");

module.exports = {
    // 转译模式: development 开发者模式 / production 产品模式
  mode: "development",
    // 输入源
  entry: "./src/index.js",
    // 输出
  output: {
      // 文件名
    filename: "main.js",
      // 输出路径
    path: path.resolve(__dirname, "dist")
  }
};
缓存需求文件名

缓存需求文件名

可以设置为生成包含MD5哈希的字符串插入文件名用于 http 缓存。

module.exports = {
   ...
   output: {
     filename: "main.[contenthash].js"
   }
};

自动生成 html

使用 html-webpack-plugin 插件。

$ yarn add html-webpack-plugin

配置:

 module.exports = {
    ...
    plugins: [
      new HtmlWebpackPlugin({
        title: 'Title',
        favicon: require('./favicon.ico'),
        template: 'src/assets/index.html'
      })
    ],
  };

对于使用自定义的 title,需要在 html 中配置:

<head>
   <title><%= htmlWebpackPlugin.options.title %></title>
</head>

引入和自动生成 css

使用加载器

$ yarn add css-loader style-loader

作用

  • css-loader 的作用是如果发现任何以 .css 结尾的文件,立即处理并读入 js 文件中。
  • style-loader 的作用是把独到的内容变为 html 文件中的 style 标签插入页面。

配置

module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'main.js',
      path: path.resolve(__dirname, 'dist')
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            'style-loader',
            'css-loader'
          ]
        }
      ]
    }
};

分离抽成 css 文件

使用插件 mini-css-extract-plugin 来打包 css 文件,把 css 样式从 js 文件中提取到单独的 css 文件。

安装

$ yarn add mini-css-extract-plugin

配置:

+  const MiniCssExtractPlugin = require('mini-css-extract-plugin')

   module.exports = {
     plugins: [
       new MiniCssExtractPlugin({
         // Options similar to the same options in webpackOptions.output
         // all options are optional
         filename: '[name].[contenthash].css',
        chunkFilename: '[id].[contenthash].css',
        ignoreOrder: false, // Enable to remove warnings about conflicting order
       }),
      ],
     module: {
       rules: [
         {
           test: /\.css$/,
           use: [
            {
              loader: MiniCssExtractPlugin.loader,
              options: {
                // you can specify a publicPath here
                // by default it uses publicPath in webpackOptions.output
                publicPath: '../',
                hmr: process.env.NODE_ENV === 'development',
              },
            },
             'css-loader',
           ],
         },
       ],
     },
};

此插件会在 dist 目录重新生成 css 文件,并在 html 中以 link 标签的形式插入。且会把所有通过 import 方式引入的 css 文件全部整合为一个文件,根据引入顺序来排列内容。

高级配置

介绍一些 Webpack 的高级配置。首先,需要深入了解一些。

插件与加载器

Webpack 的使用和拓展主要通过两种方式来实现:加载插件或安装加载器。

两者的定义和区别

  • 本意上的区别。
  • 加载器主要用来加载资源文件,插件则用来加强、扩展功能。
  • 当然 loader 也变相的扩展了 Webpack,但它更专注于转化文件。
  • plugin 的功能更加丰富,不仅局限于资源的加载。
  • loader 必定是一个文件加载另外一个文件,而 plugin 可能是综合多个文件合并为一个文件。

引入 scss

引入 .scss 文件。

注意:使用 dart-sass 代替 node-sass,因为后者已经过时且很难安装。

安装

$ yarn add sass-loader dart-sass

scss 语法示意:

$color: red;

body{
  color: $color;
}

下面示意 sass-loader 和 css-loader 、 style-loader 的链式调用。

配置(sass-loader 默认使用 node-sass,你需要把它改成 dart-sass):

module.exports = {
    ...
    module: {
       rules: [
         {
            test: /\.scss$/,
            use: [
                "style-loader", // 将 JS 字符串生成为 style 节点
                "css-loader", // 将 CSS 转化成 CommonJS 模块
                //"sass-loader"  将 Sass 编译成 CSS,如果只写这一行,默认使用 Node Sass
                {
                  loader: "sass-loader",
                  options: {
                    implementation: require('dart-sass')
                  }
                },
            ]
        }
      ]
    }
}

引入 less

引入 .less 文件。

此模块需要 Node v6.9.0+ 和 Webpack v4.0.0+。

安装:

$ yarn add less-loader less

less 语法示意:

@color: red;

body{
  color: @color;
}

下面示意 less-loader 和 css-loader 、 style-loader 的链式调用。配置:

module.exports = {
    ...
    module: {
        rules: [
          {
            test: /\.less$/,
            use: [
                "style-loader", // 将 JS 字符串生成为 style 节点
                "css-loader", // 将 CSS 转化成 CommonJS 模块
                "less-loader", // 将 Less 编译成 CSS
            ]
          },
        ]
    }
}

引入 stylus

引入 .styl 文件。

安装

$ yarn add stylus-loader stylus

stylus 语法示意:

setColor = red;

body{
  color: setColor;
}

配置

module.exports = {
    ...
    module: {
        rules: [
          {
            test: /\.less$/,
            use: [
                "style-loader", // 将 JS 字符串生成为 style 节点
                "css-loader", // 将 CSS 转化成 CommonJS 模块
                "stylus-loader", // 将 Stylus 编译成 CSS
            ]
          }
        ]
    }
}

使用 file-loader

file-loader 加载器可以根据 require 路径来把文件变成文件路径,以达到加载目的。

安装

$ yarn add file-loader

配置

module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              context: 'project',
              publicPath: 'assets',
            },
          },
        ],
      },
    ],
  },
}

浏览——快速开发

使用 webpack-dev-server 可以快速构建一个简单的 web 服务器,读取在 dist 目录下的文件,且会实时更新重载。

安装

$ yarn add webpack-dev-server

配置

  module.exports = {
    entry: {
      app: './src/index.js',
      print: './src/print.js'
    },
    devtool: 'inline-source-map',
    devServer: {
      contentBase: './dist'
    }
};

添加脚本命令

{
   "script": {
     "start": "webpack-dev-server --open"
   }
}

--open 表示自动打开浏览器。

懒加载

懒加载或按需加载,是一种很好的优化网页或应用的方式。

这种方式实际上是先把你的代码在一些逻辑点处分离开,然后完成某些操作后,立即引用或即将引用新的代码块。这样加快了应用的初始化加载速度,减轻了总体积,因为某些代码块可能永远不会被加载。

实现思路

用 import 将其当做一个函数去加载文件,得到一个 promise,成功或失败的回调。

示例

创建需要按需加载的文件。

$ touch src/lazy.js

html 中定义模块

<body>
  <div id="lazy-load"></div>
</body>

index.js

onst div = document.getElementById('lazy-load')
const button = document.createElement('button')

button.innerText = 'I am Lazy-Load'

button.onclick = () => {
  const promise = import('./lazy')
  promise.then((module)=>{
    module.default()
  },()=>{
    console.log('Error')
  })
}

div.appendChild(button)

lazy.js

export default function lazyModule() {
  console.log('This is a lazy loading module.')
  alert('This is a lazy loading module.')
}