Webpack初體驗

Webpack 是當下最熱門的前端資源模塊化管理和打包工具。它能夠將許多鬆散的模塊按照依賴和規則打包成符合生產環境部署的前端資源。還能夠將按需加載的模塊進行代碼分隔,等到實際須要的時候再異步加載。經過 loader 的轉換,任何形式的資源均可以視做模塊,好比 CommonJs 模塊、 AMD 模塊、 ES6 模塊、CSS、圖片、 JSON、Coffeescript、 LESS 等。css

1、安裝

首先要安裝 Node.js, Node.js 自帶了軟件包管理器 npm,Webpack 須要 Node.js v0.6 以上支持,建議使用最新版 Node.js。html

一、Webpack可使用npm安裝,新建一個空的練習文件夾(此處命名爲Webpack),在終端中轉到該文件夾後執行下述指令就能夠完成安裝。前端

// 切換到項目目錄
cd  /Volumes/MacSysterm/workspace/Web/Webpack

//全局安裝,之後能夠直接在命令端使用webpack命令
npm install -g webpack

//安裝到你的項目目錄,在你的項目下建立一個node_modules文件夾
npm install --save-dev webpack

二、建立package.json文件
在上述練習文件夾中建立一個package.json文件,這是一個標準的npm說明文件,裏面蘊含了豐富的信息,包括當前項目的依賴模塊,自定義的腳本任務等等。在終端中使用npm init命令能夠自動建立這個package.json文件。vue

npm init

輸入這個命令後,終端會問你一系列諸如項目名稱,項目描述,做者等信息,不過不用擔憂,若是你不許備在npm中發佈你的模塊,這些問題的答案都不重要,回車默認便可。node

三、項目中安裝Webpack做爲依賴包
package.json文件已經就緒,咱們在本項目中安裝Webpack做爲依賴包jquery

// 安裝Webpack
npm install --save-dev webpack

clipboard.png

四、建立資源文件夾
回到以前的空文件夾,並在裏面建立兩個文件夾,app文件夾和public文件夾,app文件夾用來存放原始數據和咱們將寫的JavaScript模塊,public文件夾用來存放準備給瀏覽器讀取的數據(包括使用webpack生成的打包後的js文件以及一個index.html文件)。在這裏還須要建立三個文件,index.html 文件放在public文件夾中,兩個js文件(Greeter.js和main.js)放在app文件夾中,此時項目結構以下圖所示webpack

clipboard.png

index.html文件只有最基礎的html代碼,它惟一的目的就是加載打包後的js文件(bundle.js)laravel

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Webpack Sample Project</title>
  </head>
  <body>
    <div id='root'>
    </div>
    <script src="bundle.js"></script>
  </body>
</html>

Greeter.js只包括一個用來返回包含問候信息的html元素的函數。git

//main.js 
var greeter = require('./Greeter.js');
document.getElementById('root').appendChild(greeter());

main.js用來把Greeter模塊返回的節點插入頁面。github

// Greeter.js
module.exports = function() {
  var greet = document.createElement('div');
  greet.textContent = "Hi there and greetings!";
  return greet;
};

五、在webpack中引入jquery庫
在本地項目目錄下通過npm init初始化生成package.json文件後,使用下邊命令安裝jquery包:

➜ npm install jquery --save-dev

安裝OK後,咱們就能夠在js文件中引入並使用jQuery了

// test.js
var $ = require('jquery');
$('div').html('Learning webpack,haha');

2、牛刀小試

module-one.js文件

document.write('One haha~');

module-two.js文件

document.write('Two hey~');

./js/entry.js入口文件

require('./module-one.js');

require('./module-two.js');

document.write('It works.')

clipboard.png

clipboard.png

經過命令打包生成的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;

/******/     // 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 = 2);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {

document.write('One haha~');


/***/ }),
/* 1 */
/***/ (function(module, exports) {

document.write('Two hey~');


/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {

__webpack_require__(0);

__webpack_require__(1);

document.write('It works.')


/***/ })
/******/ ]);

訪問index.html頁面

clipboard.png

3、正式使用

一、經過配置文件來使用Webpack

在當前練習文件夾的根目錄下新建一個名爲webpack.config.js的文件,並在其中進行最最簡單的配置,以下所示,它包含入口文件路徑和存放打包後文件的地方的路徑。

module.exports = {
  entry:  __dirname + "/app/main.js",//已屢次說起的惟一入口文件
  output: {
    path: __dirname + "/public",//打包後的文件存放的地方
    filename: "bundle.js"//打包後輸出文件的文件名
  }
}

注:「__dirname」是Node.js中的一個全局變量,它指向當前執行腳本所在的目錄。

如今若是你須要打包文件只須要在終端裏你運行webpack(非全局安裝需使用node_modules/.bin/webpack)命令就能夠了,這條命令會自動參考webpack.config.js文件中的配置選項打包你的項目,輸出結果以下:

clipboard.png

又學會了一種使用Webpack的方法,並且不用管那煩人的命令行參數了,有沒有感受很爽。有沒有想過若是能夠連webpack(非全局安裝需使用node_modules/.bin/webpack)這條命令均可以不用,那種感受會不會更爽~,繼續看下文。

二、更快捷的執行打包任務

執行相似於node_modules/.bin/webpack這樣的命令實際上是比較煩人且容易出錯的,不過值得慶幸的是npm能夠引導任務執行,對其進行配置後可使用簡單的**npm
start**命令來代替這些繁瑣的命令。在package.json中對npm的腳本部分進行相關設置便可,設置方法以下。

"name": "webpack-sample-project",
  "version": "1.0.0",
  "description": "Sample webpack project",
  "scripts": {
    "start": "webpack" //配置的地方就是這裏啦,至關於把npm的start命令指向webpack命令
  },
  "author": "zhang",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^1.12.9"
  }
}

注:package.json中的腳本部分已經默認在命令前添加了node_modules/.bin路徑,因此不管是全局仍是局部安裝的Webpack,你都不須要寫前面那指明詳細的路徑了。

npm的start是一個特殊的腳本名稱,它的特殊性表如今,在命令行中使用npm
start就能夠執行相關命令,若是對應的此腳本名稱不是start,想要在命令行中運行時,須要這樣用npm
run {script name}如npm run build,如下是執行npm
start後命令行的輸出顯示

如今只須要使用npm start就能夠打包文件了,有沒有以爲webpack也不過如此嘛,不過不要過小瞧Webpack,其強大的功能包含在其一系列可供配置的選項中,咱們一項項來看。

3、Webpack的強大功能

一、Source Maps使調試更容易

開發老是離不開調試,若是能夠更加方便的調試固然就能提升開發效率,不過打包後的文件有時候你是不容易找到出錯了的地方對應的源代碼的位置的,Source Maps就是來幫咱們解決這個問題的。
經過簡單的配置後,Webpack在打包時能夠爲咱們生成的source maps,這爲咱們提供了一種對應編譯文件和源文件的方法,使得編譯後的代碼可讀性更高,也更容易調試。

在webpack的配置文件中配置source maps,須要配置devtool,它有如下四種不一樣的配置選項,各具優缺點,描述以下:

clipboard.png

正如上表所述,上述選項由上到下打包速度愈來愈快,不過同時也具備愈來愈多的負面做用,較快的構建速度的後果就是對打包後的文件的的執行有必定影響。

在學習階段以及在小到中性的項目上,eval-source-map是一個很好的選項,不過記得只在開發階段使用它,繼續上面的例子,在webpack.config.js進行以下配置

// webpack.config.js
module.exports = {
  devtool: 'eval-source-map',//配置生成Source Maps,選擇合適的選項
  entry:  __dirname + "/app/main.js",
  output: {
    path: __dirname + "/public",
    filename: "bundle.js"
  }
}

cheap-module-eval-source-map方法構建速度更快,可是不利於調試,推薦在大型項目考慮da時間成本是使用。

二、使用webpack構建本地服務器

想不想讓你的瀏覽器監測你都代碼的修改,並自動刷新修改後的結果,其實Webpack提供一個可選的本地開發服務器,這個本地服務器基於node.js構建,能夠實現你想要的這些功能,不過它是一個單獨的組件,在webpack中進行配置以前須要單獨安裝它做爲項目依賴

npm install --save-dev webpack-dev-server

devserver做爲webpack配置選項中的一項,具備如下配置選項

clipboard.png

繼續把這些命令加到webpack.config.js的配置文件中,如今的配置文件以下所示:

module.exports = {
  devtool: 'eval-source-map',

  entry:  __dirname + "/app/main.js",
  output: {
    path: __dirname + "/public",
    filename: "bundle.js"
  },

  devServer: {
    contentBase: "./public",//本地服務器所加載的頁面所在的目錄
    colors: true,//終端中輸出結果爲彩色
    historyApiFallback: true,//不跳轉
    inline: true//實時刷新
  } 
}

4.Loaders

Loaders是webpack中最讓人激動人心的功能之一了。經過使用不一樣的loader,webpack經過調用外部的腳本或工具能夠對各類各樣的格式的文件進行處理,好比說分析JSON文件並把它轉換爲JavaScript文件,或者說把下一代的JS文件(ES6,ES7)轉換爲現代瀏覽器能夠識別的JS文件。或者說對React的開發而言,合適的Loaders能夠把React的JSX文件轉換爲JS文件。

Loaders須要單獨安裝而且須要在webpack.config.js下的modules關鍵字下進行配置,Loaders的配置選項包括如下幾方面:

test:一個匹配loaders所處理的文件的拓展名的正則表達式(必須)
loader:loader的名稱(必須)
include/exclude:手動添加必須處理的文件(文件夾)或屏蔽不須要處理的文件(文件夾)(可選);
query:爲loaders提供額外的設置選項(可選)
繼續上面的例子,咱們把Greeter.js裏的問候消息放在一個單獨的JSON文件裏,並經過合適的配置使Greeter.js能夠讀取該JSON文件的值,配置方法以下:

CSS

webpack提供兩個工具處理樣式表,css-loaderstyle-loader,兩者處理的任務不一樣,css-loader使你可以使用相似@importurl(...)的方法實現 require()的功能,style-loader將全部的計算後的樣式加入頁面中,兩者組合在一塊兒使你可以把樣式表嵌入webpack打包後的JS文件中。

1.安裝

//安裝
npm install --save-dev style-loader css-loader

二、配置文件中使用

module.exports = {
  devtool:"sourcemap",
  entry:"./js/entry.js",
  output:{
    filename:"bundle.js"
  },
  module: {
    loaders:[
      {
        test: /\.css$/,
        loader: 'style!css'//添加對樣式表的處理
      }
   ]
 },
}

注:感嘆號的做用在於使同一文件可以使用不一樣類型的loader

3.建立css文件,這裏咱們給body添加一個簡單的背景色pink
css/style.css文件

body{
  background: pink;
}

4.將上述css文件引入到入口entry.js中。

require('./module-one.js');

require('./module-two.js');

require('../css/style.css');  // 引入css樣式文件

document.write('It works.')

而後執行打包編譯命令:

clipboard.png

擦,怎麼報錯了-_-!!!

什麼緣由呢?

原來引入的文件寫法有問題,這裏有兩種改法:

  1. 在引入時須要加後綴loader

  2. 在配置文件中加loader後綴

第一種改法,修改引入文件:

require('./module-one.js');

require('./module-two.js');

// require('../css/style.css');  // 這樣不加loader前綴標識會報錯
require("!style-loader!css-loader!../css/style.css") // 載入 style.css

document.write('It works.')

第二種改法,修改配置文件中的寫法

module.exports = {
  devtool:"sourcemap",
  entry:"./js/entry.js",
  output:{
    filename:"bundle.js"
  },
  module: {
    loaders:[
      {
        test: /\.css$/,
      //  loader: 'style!css' //對這裏進行修改,加後綴loader
        loader: 'style-loader!css-loader'//添加對樣式表的處理
      }
   ]
 },
}

而後咱們在用命令進行編譯:

clipboard.png

OK,沒問題了,再看下加了pink的背景色的頁面。

clipboard.png

4、webpack和Vue組件開發

在開始以前,咱們先安裝babel,用ES6的語法來進行測試,安裝完以後,再進行文件的配置。

➜  webpack npm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-stage-0 babel-runtime babel-plugin-transform-runtime

一、安裝vue包

➜  webpack npm install vue vue-loader vue-html-loader vue-style-loader --save-dev

進行配置文件webpack.config.json修改:

module.exports = {
  devtool:"sourcemap",
  entry:"./js/entry.js",
  output:{
    filename:"bundle.js"
  },
  module: {
    loaders:[
      {
        test: /\.css$/,
      //  loader: 'style!css'//添加對樣式表的處理
        loader: 'style-loader!css-loader'//添加對樣式表的處理
      },
      {
        test:/\.js$/,
        loader:"babel-loader",
        exclude:/node_modules/    // 將這個目錄忽略掉,將加快加載速度

      },
      {
        test:/\.vue$/,
        loader:"vue"
      }
   ]
 },
 resolve:{
   alias:{
     'vue$':'vue/dist/vue.js'
   }
 }
};

2.新建vue文件

新建js/components/heading.vue文件

<template>
<div>
  <h1>{{ message }}</h1>
</div>
</template>

<script>
// 這裏使用的是ES6的寫法
  export default{
    data(){
      return {
        message:'hello, vue'
      }
    }
  }
</script>

在入口文件entry.js中引入該文件:

require('./module-one.js');

require('./module-two.js');

 require('../css/style.css');  // 這樣不加loader前綴標識會報錯
// require("!style-loader!css-loader!../css/style.css") // 載入 style.css

document.write('It works.');

// vue 組件操做,這裏使用ES6 babel語法
import Vue from 'vue';

Vue.component('Heading', require('./components/heading.vue'));
new Vue({
  el:"#app",
})

// 或者使用下面這種方法加載組件
/**
import Heading from './components/heading.vue';

new Vue({
  el:"#app",
  components:{ Heading }
})
*/

最後不要忘記,在index.html中添加id爲app的標示

<!-- index.html -->
<html>
<head>
  <meta charset="utf-8">
  <title> webpack學習 </title>
</head>
<body>
  <h1>Webpack is very nice !</h1>
  <div id="app">
    <!-- 這裏添加的是Vue組件 -->
    <Heading></Heading>
  </div>
  <script src="bundle.js"></script>
</body>
</html>

以上就是在webpack中使用Vue組件的步驟。

下面是須要用到的包package.json

{
  "name": "webpack",
  "version": "1.0.0",
  "description": "webpack learning",
  "main": "bundle.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Corwien",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.23.1",
    "babel-loader": "^6.3.2",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-es2015": "^6.22.0",
    "babel-preset-stage-0": "^6.22.0",
    "babel-runtime": "^6.23.0",
    "css-loader": "^0.26.2",
    "jquery": "^3.1.1",
    "style-loader": "^0.13.2",
    "vue": "^2.2.1",
    "vue-html-loader": "^1.2.4",
    "vue-loader": "^11.1.4"
  }
}

5、將示例代碼放到GitHub進行託管

1.初始化

git init

2.忽略資源文件推送到github

.gitignore文件中添加忽略的文件或文件夾名

node_modules

3.添加並推送

// 一、保存到暫存區:
git add -A

// 二、檢查 Git 狀態:
git status

// 3.保留改動並提交:
git commit -m "Initial commit"

// 4.將代碼上傳到github
$ git remote add origin git@github.com:your_username/hello_laravel.git
$ git push -u origin master

至此,示例代碼被推送到GitHub上了。

本項目被推送到GitHub的地址:
https://github.com/corwien/we...

請看原文快速入門Webpack

注:本文轉自快速入門Webpack

相關文章
相關標籤/搜索