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

想了解更多关于 JavaScript 模块和 webpack 模块的信息,请查看官方文档:模块(modules)

学习webpack要从四个核心起步:

  1. 入口(entry)
  2. 输出(output)
  3. loader
  4. 插件(plugins)

官方本文档旨在给出这些概念的高度概述,同时提供具体概念的详尽相关用例。

入口(entry)

入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
每个依赖项随即被处理,最后输出到称之为 bundles 的文件中,我们将在下一章节详细讨论这个过程。
可以通过在 webpack 配置中配置 entry 属性,来指定一个入口起点(或多个入口起点)。默认值为 ./src。
接下来我们看一个 entry 配置的最简单例子:
webpack.config.js

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

根据应用程序的特定需求,可以以多种方式配置 entry 属性。从官方文档概念入口起点章节可以了解更多信息。

出口(output)

output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist。基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。你可以通过在配置中指定一个 output 字段,来配置这些处理过程:
webpack.config.js

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'
  }
};

在上面的示例中,我们通过 output.filename 和 output.path 属性,来告诉 webpack bundle 的名称,以及我们想要 bundle 生成(emit)到哪里。可能你想要了解在代码最上面导入的 path 模块是什么,它是一个 Node.js 核心模块,用于操作文件路径。

你可能会发现术语生成(emitted 或 emit)贯穿了我们整个文档和插件 API。它是“生产(produced)”或“释放(discharged)”的特殊术语。

output 属性还有更多可配置的特性,如果你想要了解更多关于 output 属性的概念,你可以通过阅读概念章节来了解更多。

loader

loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。
本质上,webpack loader 将所有类型的文件,转换为应用程序的依赖图(和最终的 bundle)可以直接引用的模块。
注意,loader 能够 import 导入任何类型的模块(例如 .css 文件),这是 webpack 特有的功能,其他打包程序或任务执行器的可能并不支持。我们认为这种语言扩展是有很必要的,因为这可以使开发人员创建出更准确的依赖关系图。

在更高层面,在 webpack 的配置中 loader 有两个目标:

  1. test 属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。 
  2. use 属性,表示进行转换时,应该使用哪个 loader。

webpack.config.js

const path = require('path');

const config = {
  output: {
    filename: 'my-first-webpack.bundle.js'
  },
  module: {
    rules: [
      { test: /.txt$/, use: 'raw-loader' }
    ]
  }
};

module.exports = config;

以上配置中,对一个单独的 module 对象定义了 rules 属性,里面包含两个必须属性:test 和 use。这告诉 webpack 编译器(compiler) 如下信息:

“嘿,webpack 编译器,当你碰到「在 require()/import 语句中被解析为 '.txt' 的路径」时,在你对它打包之前,先使用 raw-loader 转换一下。”

重要的是要记得,在 webpack 配置中定义 loader 时,要定义在 module.rules 中,而不是 rules。然而,在定义错误时 webpack 会给出严重的警告。为了使你受益于此,如果没有按照正确方式去做,webpack 会“给出严重的警告”

loader 还有更多我们尚未提到的具体配置属性。

好啦!以上是webpack给出的三大核心概念,而且给出了配置文件相关的配置信息,怎么在webpack环境下跑起来呢?

首先还不是的安装webpack,所以不用抓狂了,看下官方指南文档如何安装webpack。

前提条件

在开始之前,请确保安装了 Node.js 的最新版本。使用 Node.js 最新的长期支持版本(LTS - Long Term Support),是理想的起步。使用旧版本,你可能遇到各种问题,因为它们可能缺少 webpack 功能以及/或者缺少相关 package 包。

本地安装(全局安装或者尝尝最新体验版请看官方指南安装文档)

最新的webpack版本是(当前练习版本v4.30.0):
要安装最新版本或特定版本,请运行以下命令之一

npm install --save-dev webpack
npm install --save-dev webpack@<version>

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

npm install --save-dev webpack-cli

对于大多数项目,我们建议本地安装。这可以使我们在引入破坏式变更(breaking change)的依赖时,更容易分别升级项目。通常,webpack 通过运行一个或多个 npm scripts,会在本地 node_modules 目录中查找安装的 webpack:

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

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

安装过程(提示了一堆的WARN,没事,先略过)

Administrator@PC-20190222QKVD MINGW64 /d/webpack_demo
$ npm install --save-dev webpack
npm WARN saveError ENOENT: no such file or directory, open 'D:webpack_demopackage.json'
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN enoent ENOENT: no such file or directory, open 'D:webpack_demopackage.json'
npm WARN webpack_demo No description
npm WARN webpack_demo No repository field.
npm WARN webpack_demo No README data
npm WARN webpack_demo No license field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modulesfsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

+ webpack@4.30.0
added 322 packages from 199 contributors and audited 4176 packages in 105.453s
found 0 vulnerabilities

Administrator@PC-20190222QKVD MINGW64 /d/webpack_demo
$ npm install --save-dev webpack-cli

> webpack-cli@3.3.2 postinstall D:webpack_demonode_moduleswebpack-cli
> node ./bin/opencollective.js

                            Thanks for using Webpack!
                 Please consider donating to our Open Collective
                        to help us maintain this package.

                 Donate: https://opencollective.com/webpack/donate

npm WARN saveError ENOENT: no such file or directory, open 'D:webpack_demopackage.json'
npm WARN enoent ENOENT: no such file or directory, open 'D:webpack_demopackage.json'
npm WARN webpack_demo No description
npm WARN webpack_demo No repository field.
npm WARN webpack_demo No README data
npm WARN webpack_demo No license field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modulesfsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

+ webpack-cli@3.3.2
added 66 packages from 28 contributors and audited 17137 packages in 30.438s
found 0 vulnerabilities 

安装完体验下上面给出的配置文件如何在当前安装目录中跑起来。

首先看下当前项目目录结构(配置文件已配置):

Administrator@PC-20190222QKVD MINGW64 /d/webpack_demo
$ ll
total 205
drwxr-xr-x 1 Administrator 197121      0 五月    5 09:10 dist/
drwxr-xr-x 1 Administrator 197121      0 五月    5 09:06 node_modules/
-rw-r--r-- 1 Administrator 197121 125479 五月    5 09:06 package-lock.json
drwxr-xr-x 1 Administrator 197121      0 五月    5 09:10 path/
-rw-r--r-- 1 Administrator 197121    294 五月    5 10:51 webpack.config.js 

上面项目目录结构是已经执行过webpack命令后的目录,如果您是只是执行了安装不会出现这样的,至少是没有dist目录和package-lock.json文件的。

webpack.config.js文件是我们新建的文件。

webpack.config.js文件代码文档中已经给出:

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;

那上面新增的目录结构是怎么生成的呢,看下面:

Administrator@PC-20190222QKVD MINGW64 /d/webpack_demo
$ webpack
Hash: ecceaa813d657c671fc8
Version: webpack 4.30.0
Time: 1808ms
Built at: 2019-05-05 10:50:17
                     Asset       Size  Chunks             Chunk Names
my-first-webpack.bundle.js  930 bytes       0  [emitted]  main
Entrypoint main = my-first-webpack.bundle.js
[0] ./path/to/my/entry/file.js 0 bytes {0} [built]

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/concepts/mode/ 

看上面的输出,file.js文件 0 字节,因为就没写任何内容在里面。

my-first-webpack.bundle.js这个文件是不是生成了呢,而且是在dist目录下,package-lock.json是4.30.0版本才会出现的,依据官方文档说明

下面接着看下第四核心点插件:

插件(plugins)

loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务。
想要使用一个插件,你只需要 require() 它,然后把它添加到 plugins 数组中。多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建它的一个实例。
webpack.config.js(更新此文件)

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

const config = {
  module: {
    rules: [
      { test: /.txt$/, use: 'raw-loader' }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};

module.exports = config;

接着再看下,抛出错误了吧,亲。

Administrator@PC-20190222QKVD MINGW64 /d/webpack_demo
$ webpack
D:webpack_demonode_moduleswebpack-clibincli.js:74
                                throw err;
                                ^

Error: Cannot find module 'html-webpack-plugin'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:582:15)
    at Function.Module._load (internal/modules/cjs/loader.js:508:25)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (D:webpack_demonode_modulesv8-compile-cachev8-compile-cache.js:159:20)
    at Object.<anonymous> (D:webpack_demowebpack.config.js:1:89)
    at Module._compile (D:webpack_demonode_modulesv8-compile-cachev8-compile-cache.js:178:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
    at Module.load (internal/modules/cjs/loader.js:600:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
    at Function.Module._load (internal/modules/cjs/loader.js:531:3)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (D:webpack_demonode_modulesv8-compile-cachev8-compile-cache.js:159:20)
    at WEBPACK_OPTIONS (D:webpack_demonode_moduleswebpack-clibinutilsconvert-argv.js:115:13)
    at requireConfig (D:webpack_demonode_moduleswebpack-clibinutilsconvert-argv.js:117:6)
    at D:webpack_demonode_moduleswebpack-clibinutilsconvert-argv.js:124:17
    at Array.forEach (<anonymous>)
    at module.exports (D:webpack_demonode_moduleswebpack-clibinutilsconvert-argv.js:122:15)
    at yargs.parse (D:webpack_demonode_moduleswebpack-clibincli.js:71:45)
    at Object.parse (D:webpack_demonode_modulesyargsyargs.js:567:18)
    at D:webpack_demonode_moduleswebpack-clibincli.js:49:8
    at Object.<anonymous> (D:webpack_demonode_moduleswebpack-clibincli.js:375:3)
    at Module._compile (internal/modules/cjs/loader.js:701:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
    at Module.load (internal/modules/cjs/loader.js:600:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
    at Function.Module._load (internal/modules/cjs/loader.js:531:3)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (internal/modules/cjs/helpers.js:22:18)
    at module.exports.filename (D:Program Filesnodejsnode_globalnode_moduleswebpack-clinode_modulesimport-localindex.js:16:66)
    at D:Program Filesnodejsnode_globalnode_moduleswebpack-clibincli.js:13:6 

Error: Cannot find module 'html-webpack-plugin':提示插件找不到,需要安装,上面配置文件中已经提示通过nmp安装。

那就按照吧,又来一堆WARN警告,会提示警告那就没问题,就是切少package.json文件,默认安装的是html-webpack-plugin@3.2.0

Administrator@PC-20190222QKVD MINGW64 /d/webpack_demo
$ npm install html-webpack-plugin
npm WARN saveError ENOENT: no such file or directory, open 'D:webpack_demopackage.json'
npm WARN enoent ENOENT: no such file or directory, open 'D:webpack_demopackage.json'
npm WARN webpack_demo No description
npm WARN webpack_demo No repository field.
npm WARN webpack_demo No README data
npm WARN webpack_demo No license field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modulesfsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

+ html-webpack-plugin@3.2.0
added 51 packages from 70 contributors and audited 18424 packages in 28.847s
found 0 vulnerabilities

再次webpack,发现什么没有?插件报错消失了吧,然后呢,看警告啊,说什么开发环境,生产环境没有设置值,需要设置,烦哦。还提示index.html文件,咋地啦?

Administrator@PC-20190222QKVD MINGW64 /d/webpack_demo
$ webpack
Hash: 335a315e65a27f1ae8f5
Version: webpack 4.30.0
Time: 1678ms
Built at: 2019-05-05 11:49:12
 1 asset
Entrypoint main = my-first-webpack.bundle.js
[0] ./path/to/my/entry/file.js 0 bytes {0} [built]

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/concepts/mode/

ERROR in   Error: Child compilation failed:
  Entry module not found: Error: Can't resolve 'D:webpack_demosrcindex.html'   in 'D:webpack_demo':
  Error: Can't resolve 'D:webpack_demosrcindex.html' in 'D:webpack_demo'

  - compiler.js:79 childCompiler.runAsChild
    [webpack_demo]/[html-webpack-plugin]/lib/compiler.js:79:16

  - Compiler.js:306 compile
    [webpack_demo]/[webpack]/lib/Compiler.js:306:11

  - Compiler.js:631 hooks.afterCompile.callAsync.err
    [webpack_demo]/[webpack]/lib/Compiler.js:631:15

  - Hook.js:154 AsyncSeriesHook.lazyCompileHook
    [webpack_demo]/[tapable]/lib/Hook.js:154:20

  - Compiler.js:628 compilation.seal.err
    [webpack_demo]/[webpack]/lib/Compiler.js:628:31

  - Hook.js:154 AsyncSeriesHook.lazyCompileHook
    [webpack_demo]/[tapable]/lib/Hook.js:154:20

  - Compilation.js:1329 hooks.optimizeAssets.callAsync.err
    [webpack_demo]/[webpack]/lib/Compilation.js:1329:35

  - Hook.js:154 AsyncSeriesHook.lazyCompileHook
    [webpack_demo]/[tapable]/lib/Hook.js:154:20

  - Compilation.js:1320 hooks.optimizeChunkAssets.callAsync.err
    [webpack_demo]/[webpack]/lib/Compilation.js:1320:32

  - index.js:319 taskRunner.run
    [webpack_demo]/[terser-webpack-plugin]/dist/index.js:319:9

  - TaskRunner.js:44 TaskRunner.run
    [webpack_demo]/[terser-webpack-plugin]/dist/TaskRunner.js:44:7

  - index.js:225 TerserPlugin.optimizeFn
    [webpack_demo]/[terser-webpack-plugin]/dist/index.js:225:18

  - Hook.js:154 AsyncSeriesHook.lazyCompileHook
    [webpack_demo]/[tapable]/lib/Hook.js:154:20

  - Compilation.js:1315 hooks.additionalAssets.callAsync.err
    [webpack_demo]/[webpack]/lib/Compilation.js:1315:36

  - Hook.js:154 AsyncSeriesHook.lazyCompileHook
    [webpack_demo]/[tapable]/lib/Hook.js:154:20

  - Compilation.js:1311 hooks.optimizeTree.callAsync.err
    [webpack_demo]/[webpack]/lib/Compilation.js:1311:32

  - Hook.js:154 AsyncSeriesHook.lazyCompileHook
    [webpack_demo]/[tapable]/lib/Hook.js:154:20

  - Compilation.js:1248 Compilation.seal
    [webpack_demo]/[webpack]/lib/Compilation.js:1248:27

  - Compiler.js:625 compilation.finish.err
    [webpack_demo]/[webpack]/lib/Compiler.js:625:18

  - Compilation.js:1171 hooks.finishModules.callAsync.err
    [webpack_demo]/[webpack]/lib/Compilation.js:1171:4

  - Hook.js:154 AsyncSeriesHook.lazyCompileHook
    [webpack_demo]/[tapable]/lib/Hook.js:154:20

  - Compilation.js:1163 Compilation.finish
    [webpack_demo]/[webpack]/lib/Compilation.js:1163:28

  - Compiler.js:622 hooks.make.callAsync.err
    [webpack_demo]/[webpack]/lib/Compiler.js:622:17

  - Compilation.js:1095 _addModuleChain
    [webpack_demo]/[webpack]/lib/Compilation.js:1095:12

  - Compilation.js:947 errorAndCallback.bail.err
    [webpack_demo]/[webpack]/lib/Compilation.js:947:6

  - Compilation.js:980 moduleFactory.create
    [webpack_demo]/[webpack]/lib/Compilation.js:980:14

  - NormalModuleFactory.js:397 factory
    [webpack_demo]/[webpack]/lib/NormalModuleFactory.js:397:22

Child html-webpack-plugin for "index.html":

    ERROR in Entry module not found: Error: Can't resolve 'D:webpack_demosrcindex.html' in 'D:webpack_demo' 

模式

通过选择 development 或 production 之中的一个,来设置 mode 参数,你可以启用相应模式下的 webpack 内置的优化

module.exports = {
    mode: 'production'
};

官方概念文档已经说明了,更新下webpack.config.js文件,同时在目录下新建src目录,新建的src目录下新建个空文件:index.html,然后webpack看下情况吧,没问题了吧,有提示的请仔细查看,dist目录下是不是生成了index.html文件呢?

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 HtmlWebpackPlugin({template: './src/index.html'})
    ],
    mode: 'production'
};
module.exports = config;
Administrator@PC-20190222QKVD MINGW64 /d/webpack_demo
$ webpack
Hash: d3004d411e049aa87ba1
Version: webpack 4.30.0
Time: 1992ms
Built at: 2019-05-05 11:55:45
                     Asset       Size  Chunks             Chunk Names
                index.html   73 bytes          [emitted]
my-first-webpack.bundle.js  930 bytes       0  [emitted]  main
Entrypoint main = my-first-webpack.bundle.js
[0] ./path/to/my/entry/file.js 0 bytes {0} [built]
Child html-webpack-plugin for "index.html":
     1 asset
    Entrypoint undefined = index.html
    [0] ./node_modules/html-webpack-plugin/lib/loader.js!./src/index.html 194 bytes {0} [built]
    [2] (webpack)/buildin/global.js 472 bytes {0} [built]
    [3] (webpack)/buildin/module.js 497 bytes {0} [built]
        + 1 hidden module 

完结!

点赞(3) 打赏

评论列表 共有 0 条评论

暂无评论

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部