Webpack 快速入门指南(一)

简介

webpack 是一个前端资源加载/打包工具。

webpack 是一个 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

webpack 可以将多种静态资源(js、css、less、sass等) 转换、打包成一个或多个静态文件。

在 webpack 中,"一切皆模块”,它把 js 文件视作模块,其他的(如 css、png、sass 等)文件也视作模块。

webpack 4.0.0 的特性

  • CLI 被单独分离到 webpack-cli 包,需单独安装。
  • 默认将 ./src/index.js 作为入口,将 ./dist/main.js 作为输出。
  • 引入开发(development)和生产(production)模式,必须通过 --mode 选项指定一种模式。
  • 移除了一些常用的内置插件,可使用新的内置插件代替。

主要概念

webpack 是高度可配置的,默认的配置文件是 webpack.config.js,你需要先理解四个主要概念:

  • 入口(entry)
  • 输出(output)
  • loader
  • 插件(plugins)

入口(entry)

入口 指定了 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。

进入入口后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。

每个依赖项随即被处理,最后输出到称之为 bundles 的文件中。

可以通过在 webpack 配置中配置 entry 属性,来指定一个或多个入口起点。

下面是一个 entry 配置的最简单例子:

webpack.config.js

module.exports = {
  entry: './path/to/my/entry/file.js'
};

输出(output)

输出(output)告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件。

你可以在配置中通过 output 属性进行设定。

const path = require('path');

module.exports = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js'
  }
};

loader

loader 使 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包功能,对它们进行处理。

loader 能够 import 导入任何类型的模块(例如 .css 文件)。

在 webpack 的配置中 loader 有两个目标:

  • test 属性,指定哪些文件需要被 loader 转换。
  • use 属性,指定进行转换时,应该使用哪个 loader。
const path = require('path');

const config = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js'
  },
  module: {
    rules: [
      { test: /\.txt$/, use: 'raw-loader' }
    ]
  }
};

module.exports = config;

上述示例中,对一个单独的 module 对象定义了 rules 属性,rules 属性里面包含两个必须属性:test 和 use。它告诉 webpack 的编译器:当碰到「require()/import 语句中被解析为 '.txt' 的路径」时,在对它打包之前,先使用 raw-loader 进行转换。

注意: 在 webpack 配置中定义 loader 时,要定义在 module.rules 中,而不是 rules。

插件(plugins)

loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。

插件的功能包括,从打包优化和压缩,一直到重新定义环境中的变量。

插件接口功能极其强大,可以用来处理各种各样的任务。

想要使用一个插件,你只需要 require() 它,然后把它添加到 plugins 数组中。多数插件可以自定义参数。

const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装
const webpack = require('webpack'); // 用于访问内置插件
const path = require('path');

const config = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js'
  },
  module: {
    rules: [
      { test: /\.txt$/, use: 'raw-loader' }
    ]
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin(),
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};

module.exports = config;

安装

前提条件

在安装 webpack 之前,你必须先安装 node.js,然后通过 node.js 的 npm 工具来安装 webpack。

本地安装

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

npm install --save-dev webpack

npm install --save-dev webpack@

推荐本地安装。这可以使我们在引入破坏式变更的依赖时,更容易分别升级项目。通常,webpack 通过运行一个或多个 npm 脚本,会在本地 node_modules 目录中查找安装的 webpack:

"scripts": {
    "start": "webpack --config webpack.config.js"
}

说明:当你在本地安装 webpack 后,你能够从 node_modules/.bin/webpack 访问它的 bin 版本。

注意: webpack 4.0.0 中,将 CLI 单独分离到了 webpack-cli 包中,如果想在 CLI 中运行 webpack,就必须单独安装 webpack-cli。

npm install --save-dev webpack-cli

全局安装

npm install --global webpack

npm install --global webpack-cli

初步使用

webpack 用于编译 JavaScript 模块。一旦完成安装,你就可以通过 webpack 的 CLI 或 API 与 webpack 进行交互。

基本安装

首先,我们创建一个项目目录 webpack-demo ,初始化 npm,以及在本地安装 webpack:

mkdir webpack-demo && cd webpack-demo

npm init -y

npm install --save-dev webpack

单独安装 webpack-cli:

npm install --save-dev webpack-cli

并将 webpack-cli 的命令文件所在目录(D:\phpStudy\WWW\webpack-demo\node_modules\.bin),添加至系统的环境变量 PATH 中。如此,就可以在命令行中的任何工作目录直接使用 webpack 命令了。

然后,在 webpack-demo 目录中,创建 index.html,内容如下:


  
    Getting Started
    
  
  
    
  

在 webpack-demo 中,新建 src 目录,并在 src 目录中创建 index.js ,内容如下:

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

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

  return element;
}

document.body.appendChild(component());

在此示例中,

在这个设置中,index.js 显式要求引入的 lodash 必须存在,然后将它绑定为 _(没有全局作用域污染)。通过声明模块所需的依赖,webpack 能够利用这些信息去构建依赖图,然后使用图生成一个优化过的,会以正确顺序执行的 bundle。

然后,创建 bundle 文件。

webpack --mode development --entry ./src/index.js --output ./dist/bundle.js

在浏览器中访问 http://localhost/webpack-demo/dist/index.html ,如果一切都正常,你应该能看到以下文本:'Hello webpack'。

使用 webpack 的配置文件

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

webpack.config.js

const path = require('path');

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

现在,让我们通过 webpack.config.js 配置文件,再次执行构建:

webpack --mode development --config webpack.config.js

说明: 如果 webpack.config.js 文件存在,webpack 命令将默认选择使用它。

我们在这里使用 --config 选项只是向你表明,可以传递任何名称的配置文件。这对于需要拆分成多个文件的复杂配置非常有用。

NPM 脚本(npm scripts)

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

{
  ...
  "scripts": {
    "dev": "webpack --mode development"
  },
  ...
}

说明: scripts 的值是一个 json,该 json 可以包含多键值对,其中,键代表可以通过 npm run 来运行的别名(如 dev),而值代表可以在 CLI 中运行的命令及其选项。

现在,来测试你的别名是否可以正常运行:

npm run dev

通过向 npm run dev 命令和你的参数之间添加两个中横线,可以将自定义参数传递给 webpack。例如:

npm run dev -- --colors

结论

现在,你已经实现了一个基本的构建过程。下面来学习如何通过 webpack 来管理资源,例如图片、字体。

管理资源

如果你是从开始一直遵循指南的示例,就会有一个小项目,显示 "Hello webpack"。现在我们尝试整合一些其他资源,比如图像,看看 webpack 如何处理。

webpack 最出色的功能之一就是,除了 JavaScript,还可以通过 loader 引入任何其他类型的文件。让我们从 CSS 开始起步。

加载 CSS

为了从 JavaScript 模块中 import 一个 CSS 文件,你需要在 module 配置中 安装并添加 style-loader 和 css-loader:

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$/,
                use: [
                    'style-loader',
                    'css-loader'
                ]
            }
        ]
    }
};

webpack 根据正则表达式,来确定应该查找哪些文件,并将其提供给指定的 loader。在这种情况下,以 .css 结尾的全部文件,都将被提供给 style-loader 和 css-loader。

这使你可以在依赖于此样式的文件中 import './style.css'。当该模块运行时,含有 CSS 字符串的