注:下文所使用的环境均为Mac
Webpack的官方文档:
https://webpack.js.org/concepts/
1. 安装webpack
打开Terminal。
//-新建文件夹
mkdir webpack-test
//-进入文件夹
cd webpack-test
//-初始化npm
npm init
//-安装webpack
npm install webpack --save-dev
安装完成后,会在文件夹内看到package.json和mode_modules。
webpack-test
└── node_modules/
│
└── package.json
2. webpack打包实践
(1) 打包单个js文件
使用IDE打开该工程文件夹,新建一个hello.js文件。
function hello(str){
alert(str);
}
在Terminal中,使用webpack将hello.js打包为hello.bundle.js。
webpack hello.js hello.bundle.js
打开hello.bundle.js如下:
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {
function hello(str){
alert(str);
}
/***/ })
/******/ ]);
在文件的尾部可以看到写到hello.js里面的内容,而前面有很多代码是webpack在打包的时候生成的。同时,webpack给函数进行了编号。
(2) 打包原理探究
[1] js中的require打包
新建文件world.js
//-world.js
function world(){
return{
}
}
在hello.js 中引用world.js(使用common.js的方式)。
//-hello.js
require('./world.js');
function hello(str){
alert(str);
}
重新打包一次。
webpack hello.js hello.bundle.js
可以看到 hello.js的模块编号为0,world.js模块编号为1。再看下打包出来的hello.bundle.js(略过头部)。
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
__webpack_require__(1);
function hello(str){
alert(str);
}
/***/ }),
/* 1 */
/***/ (function(module, exports) {
function world(){
return {
}
}
可以看出hello.js中的require被替换成了webpack内置函数的require——__webpack_require__(1)
。
所以,webpack就是以这样的方式寻找依赖并打包在一起。这就是webpack的工作方式。
[2] css打包
1) 打包尝试
在根目录下,新建style.css文件。
/* style.css */
body{
background-color: red;
}
在hello.js中require('./style.css')
,再对hello.js进行打包。会发现报错了,提示You may need an appropriate loader to handle this file type.
由此,webpack处理css文件是需要依赖loader的。
2) 打包方法
所以,需要在项目目录下安装loader,css-loader
以及 style-loader
,如下:
npm install css-loader style-loader --save-dev
同时,在引用时指定loader。
//-hello.js
//在引用前先经过css-loader的处理
require('css-loader!./style.css')
完成上述操作后,再打包hello.js,在打包后生成的代码中,我们可以看到:
// module
exports.push([module.i, "body{\n background-color: red;\n}", ""]);
新建index.html文件:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script type="text/javascript" src="hello.bundle.js"></script>
</body>
</html>
运行页面后发现,css并没有起效。这里我们就需要用到style-loader。
//-hello.js
//在引用前先经过css-loader的处理
require('style-loader!css-loader!./style.css')
webpack打包后再运行页面,样式生效了。发现css中的代码被加上了style标签,加入到了head里面。
3) 打包总结(命令行打包)
css-loader使webpack可以处理.css的文件;style-loader把css-loader处理完的文件,放入新建的style标签中,再插入html中。
[问题] 每次引用css都要加上loader很麻烦,有办法解决吗?
[解答] 可以通过命令行工具,使css对应相应的loader,如下:
使用--module-bind
将css文件绑定到loader上。
webpack hello.js hello.bundle.js --module-bind 'css=style-loader!css-loader'
4) 自动打包
按照上述方法,每当文件改变,都需要使用命令行来打包,这样非常繁琐。所以,使用--watch
可以做到文件更新,自动打包。
webpack hello.js hello.bundle.js --module-bind 'css=style-loader!css-loader' --watch
(3) webpack参数
如同--watch
,webpack还有很多参数,可以在命令行中输入如下命令查看。
webpack --help
举例:
[1] 查看打包过程--progess
webpack hello.js hello.bundle.js --module-bind 'css=style-loader!css-loader' --progess
可以看到有百分比的读条。
[2] 查看打包模块--display-modules
webpack hello.js hello.bundle.js --module-bind 'css=style-loader!css-loader' --display-modules
会把所有打包模块列出来,以及使用的loader。
[3] 查看打包原由--display-reasons
webpack hello.js hello.bundle.js --module-bind 'css=style-loader!css-loader' --display-reasons
由上图,为啥打包hello.js还打包了其他文件?这里列出了require项。