每次學新東西總感受本身是否是變笨了,看了幾個博客,試着試着就跑不下去,無奈只有去看官方文檔。 webpack是基於node的。先安裝最新的node。javascript
1.初始化html
安裝node後,新建一個目錄,好比html5。cmd中切到當前文件夾。html5
npm init -y
java
這個命令會建立一個默認的package.json。它包含了項目的一些配置參數,經過它能夠進行初始安裝。詳細參數:https://docs.npmjs.com/files/package.json。node
不要y參數的話,會在命令框中設置各項參數,但以爲沒啥必要。webpack
2.安裝webpackes6
`npm` `install` `webpack --save-dev`
將webpack安裝到當前目錄。雖然npm install webpack -g 能夠講webpack安裝到全局,可是容易出現一些模塊找不到的錯誤,因此最好仍是安裝到當前目錄下。web
3.目錄結構npm
webpack是一款模塊加載各類資源並打包的工具。因此先建一個以下的目錄結構:json
app包含的開發中的js文件,一個組件,一個入口。build中就是用來存放打包以後的文件的。webpack.config.js 顧名思義用來配置webpack的。package.json就不用說了。
component.js
`export` `default` `function` `() {` `var` `element = document.createElement(``'h1'``);` `element.innerHTML =` `'Hello world'``;` `return` `element;` `}`
component.js 是輸出一個內容爲h1元素。export default 是ES6語法,表示指定默認輸出。import的時候不用帶大括號。
index.js
`import component from` `'./component'``;` `document.body.appendChild(component());`
index.js 的做用就是引用Component模塊,並在頁面上輸出一個h1元素。但完成這個還須要一個插件,由於目前咱們尚未index.html文件。
`npm` `install` `html-webpack-plugin --save-dev`
html-webpack-plugin的用來生成html,將其也安裝到開發目錄下面。
4.設置 webpack 配置文件
咱們須要經過webpack.config.js文件告訴webpack如何開始。配置文件至少須要一個入口和一個輸出。多個頁面就須要多個入口。node的path模塊
`const path = require(``'path'``);` `const HtmlWebpackPlugin = require(``'html-webpack-plugin'``);` `const PATHS = {` `app: path.join(__dirname,` `'app'``),` `build: path.join(__dirname,` `'build'``),` `};` `module.exports = {` `entry: {` `app: PATHS.app,` `},` `output: {` `path: PATHS.build,` `filename:` `'[name].js'``,` `},` `plugins: [` `new` `HtmlWebpackPlugin({` `title:` `'Webpack demo'``,` `}),` `],` `};`
第一次看到這個配置文件是有點懵,主要是exports,分三個部分,一個入口,一個輸出,一個插件。入口指向了app文件夾。默認會把包含"index.js"的文件做爲入口。輸出指定了build地址和一個文件名;[name]這兒表示佔位符,能夠當作webpack提供的一個變量。這個具體後面再看。而HtmlWebpackPlugin會生成一個默認的html文件。
5.打包
有了以上準備,直接輸入 webpack 就能運行了。
這個輸出包含了Hash(每次打包值都不一樣),Version,Time(耗時)。以及輸出的文件信息。這時打開build文件夾,發現多了一個app.js和index.html文件,雙擊index.html:
也能夠修改下package.json
`{` `"name"``:` `"Html5"``,` `"version"``:` `"1.0.0"``,` `"description"``:` `""``,` `"main"``:` `"index.js"``,` `"scripts"``: {` `"build"``:` `"webpack"` `},` `"keywords"``: [],` `"author"``:` `""``,` `"license"``:` `"ISC"``,` `"devDependencies"``: {` `"html-webpack-plugin"``:` `"^2.28.0"``,` `"webpack"``:` `"^2.2.1"` `}` `}`
指定build。在cmd中執行npm run build 獲得一樣的結果
出現helloword。再看下文件內容
index.html:
`<!DOCTYPE html>` `<``html``>` `<``head``>` `<``meta` `charset``=``"UTF-8"``>` `<``title``>Webpack demo</``title``>` `</``head``>` `<``body``>` `<``script` `type``=``"text/javascript"` `src``=``"app.js"``></``script``></``body``>` `</``html``>`
默認引用了app.js。
六、解析
app.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;` `/******/` `// 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, __webpack_exports__, __webpack_require__) {` `"use strict"``;` `/* harmony default export */` `__webpack_exports__[``"a"``] =` `function` `() {` `var` `element = document.createElement(``'h1'``);` `element.innerHTML =` `'Hello world'``;` `return` `element; `};` `/***/` `}),` `/* 1 */` `/***/` `(``function``(module, __webpack_exports__, __webpack_require__) {` `"use strict"``;` `Object.defineProperty(__webpack_exports__,` `"__esModule"``, { value:` `true` `});` `/* harmony import */` `var` `__WEBPACK_IMPORTED_MODULE_0__component__ = __webpack_require__(0);` `document.body.appendChild(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__component__[``"a"` `/* default */``])());` `/***/` `})` `/******/` `]);`
而app.js內容比較多了。總體是一個匿名函數。
`(``function``(module) {` `})([(``function` `(){}),` `function``() {}])`
app文件夾中的兩個js文件成了這兒的兩個模塊。函數最開始是從__webpack_require__開始
`return` `__webpack_require__(__webpack_require__.s = 1);`
這裏指定從模塊1執行(賦值語句的返回值爲其值)。而模塊1的調用是經過__webpack_require__的這句執行的。
<u>複製代碼</u> 代碼以下:
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
經過call調用模塊的主要做用是爲了把參數傳過去。
`(``function``(module, __webpack_exports__, __webpack_require__) {` `"use strict"``;` `Object.defineProperty(__webpack_exports__,` `"__esModule"``, { value:` `true` `});` `/* harmony import */` `var` `__WEBPACK_IMPORTED_MODULE_0__component__ = __webpack_require__(0);` `document.body.appendChild(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__component__[``"a"` `/* default */``])());` `/***/` `})`
webpack_require 每加載一個模塊都會先去模塊緩存中找,沒有就新建一個module對象:
`var` `module = installedModules[moduleId] = {` `i: moduleId,` `l:` `false``,` `exports: {}` `};`
模塊1中加載了模塊0,
`var` `__WEBPACK_IMPORTED_MODULE_0__component__ = __webpack_require__(0);`
WEBPACK_IMPORTED_MODULE_0__component 返回的是這個模塊0的exports部分。而以前Component.js的默認方法定義成了
`__webpack_exports__[``"a"``] =` `function` `() {` `var` `element = document.createElement(``'h1'``);` `element.innerHTML =` `'Hello world'``;` `return` `element;` `}`
因此再模塊1的定義經過"a「來獲取這個方法:
<u>複製代碼</u> 代碼以下:
document.body.appendChild(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__component__["a" /* default */])());
這樣就完整了,但這裏使用了__webpack_require__.i 將原值返回。
`/******/` `// identity function for calling harmony imports with the correct context` `/******/` `__webpack_require__.i =` `function``(value) {` `return` `value; };`
不太明白這個i函數有什麼做用。這個註釋也不太明白,路過的大神但願能夠指點下。
小結:
webpack經過一個當即執行的匿名函數將各個開發模塊做爲參數初始化,每一個js文件(module)對應一個編號,每一個js中export的方法或者對象有各自指定的關鍵字。經過這種方式將全部的模塊和接口方法管理起來。而後先加載最後的一個模塊(應該是引用別的模塊的模塊),這樣進而去觸發別的模塊的加載,使整個js運行起來。到這基本瞭解了webpack的功能和部分原理,但略顯複雜,且沒有感覺到有多大的好處。繼續探索。