模块化的相关库和工具已经很多了,包括require.js、sea.js和一些工程化工具webpack、gulp、grant。那么我们该如何选择呢? 其实,我们只需要掌握了其中一种模块化的方案即可,因为这里最重要的是思想,而不是工具。在这些工具之中,webpack无疑是非常火的,并且在现在和未来也将大有可为,所以,这篇文章就好好的说说webpack!
参考文章:webpack官方api文档
https://doc.webpack-china.org/loaders/less-loader/
webpack安装的loader方式。
什么是webpack?
webpack是一款打包工具,其中的modules包括css、js、image等,通过webpack我们可以轻松的解决项目的依赖问题、模块化问题、后期的压缩测试等问题。
为什么使用webpack?
好用啊! 相比于requirejs、gulp、grunt, webpack的优势都是非常明显的!
开始
本地安装webpack
mkdir webpack-demo && cd webpack-demo npm init -y npm install --save-dev webpack
-
mkdir用于创建文件夹,&&标识当完成创建文件夹之后要做的指令。 cd 返回文件夹。
- npm init -y 即创建package.json,通过-y,我们可以创建默认的信息。
- --save-dev即将安装webpack记录在package.json中的dependicies中。
- 注意:我们建议本地安装webpack,而不是全局安装webpack,因为全局的webpack将会限制你所使用的版本,在某些情况下回出错。比如,安装loader和plugins可能会依赖最新的webpack,这样,使用本地安装webpack就是最好的选择了。
获取webpack相关命令
./node_modules/.bin/webpack --help # Shows a list of valid cli commands .\node_modules\.bin\webpack --help # For windows users webpack --help # If you installed webpack globally
- 即如果我们全局安装了webpack,直接webpack --help就可以获得相关的命令。
- 如果我们是本地安装,就需要进入node_modules下的bin文件夹中执行 webpack --help 命令, 否则会出错。(注意Mac和Windows下的区别)
创建app文件夹并创建index.js
function component () { var element = document.createElement('div'); /* lodash is required for the next line to work */ element.innerHTML = _.join(['Hello','webpack'], ' '); return element; } document.body.appendChild(component());
这段代码即将一个创建的div插入到body中去。
注意: 这里的_并没有定义,我们在后面会引入lodash,才能支持使用_。
为执行index.js,在根目录下创建index.html
<html>
<head>
<title>webpack 2 demo</title>
<script src="https://unpkg.com/lodash@4.16.6"></script>
</head>
<body>
<script src="app/index.js"></script>
</body>
</html>
OK! 到这里我们的这个项目就可以运行了,因为还没有做任何的配置,所以直接在浏览器中打开index.html可发现hello webpack。
总结一下可以发现,在两个js中,下面的js对上面的js的依赖的,lodash必须加载完成之后,index.js才能正常执行。但是,index.js对lodash的依赖又是隐式的,因为index.js并没有声明它需要lodash,而是直接认为_是全局中存在的,所以直接使用。
这样管理JavaScript存在下面的两个问题:
- 如果lodash不再存在后者两个js的顺序反了,那么这个应用将无法执行。
- 如果lodash存在但是没有被用到,即应用中不需要indexjs了,那么浏览器下载lodash就是多余的了。
为了解决上面两个问题,我们做出下面的改变。
为了将indexjs依赖的lodash和index打包在一起(形成明显的依赖关系),我们先安装lodash:
npm install --save lodash
在index.js中引入lodash
在index.js的最上方添加:
import _ from 'lodash';
注意: 这是引入lodash模块的_变量,使用import,这是一条语句,最后要添加分好。
index.html中只引入一个最后打包的文件
我们将index.html内容修改如下:
<html>
<head>
<title>webpack 2 demo</title>
</head>
<body>
<script src="dist/bundle.js"></script>
</body>
</html>
即只保留了一个bundle.js,bundle.js是什么呢?实际上是最后我们通过webpack打包出来的文件,后面还会讲到。
到这里,我们就可以看到index.js是明确的依赖lodash的,并且将_绑定,这样,就不会造成全局污染了。
通过声明一个module(这里可以认为是index.js)所需要的依赖,webpack就可以利用这个信息来创建一个依赖图表,然后通过这个依赖图标将所需依赖按照正确的顺序打包到一个文件中。 对于没有用到的依赖将不会打包到文件中去。
现在,我们就可以来使用webpack运行项目了,并且把index.js当做入口文件,把bundle.js当做出口文件,且对于一个页面需要的所有代码都会被打包到这个出口文件中。
.\node_modules\.bin\webpack app/index.js dist/bundle.js
执行上述命令之后的结果如下:
C:\Users\Administrator\Desktop\webpack-demo>.\node_modules\.bin\webpack app/index.js dist/bundle.js Hash: df00524299afa8ed4535 Version: webpack 2.5.1 Time: 478ms Asset Size Chunks Chunk Names bundle.js 544 kB 0 [emitted] [big] main [0] ./~/.4.17.4@lodash/lodash.js 540 kB {0} [built] [1] ./app/index.js 276 bytes {0} [built] [2] (webpack)/buildin/global.js 509 bytes {0} [built] [3] (webpack)/buildin/module.js 517 bytes {0} [built]
然后在浏览器中打开index.html我们就可以看到成功的打包结果了,并且在根目录下产生了一个dist文件,其中包含了bundle.js。说明:dist是distribution,即分发的意思。
存在的问题: 原本就几十行的代码通过webpack的打包之后达到了惊人的17000多行,大小达到了500余k,这是不是会影响性能呢?
解释:并非如此,因为lodash就有17000行了。
这是bundle.js在开头添加的70行代码:
/******/ (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; /******/ /******/ // identity function for calling harmony imports with the correct context /******/ __webpack_require__.i = function(value) { return value; }; /******/ /******/ // 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 = 1); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) {