webpack-入門

參考:http://www.javashuo.com/article/p-gqgzutje-er.htmlcss

1.什麼是webpack,爲何要使用它html

  一些優秀的網站每每有許多JavaScript文件,不少依賴項,爲了簡化開發的複雜度,前端有不少實踐方法:前端

  • 模塊化,讓咱們能夠把複雜的程序細化爲小的文件;
  • 相似於TypeScript這種在JavaScript基礎上拓展的開發語言:使咱們可以實現目前版本的JavaScript不能直接使用的特性,而且以後還能轉換爲JavaScript文件使瀏覽器能夠識別;
  • Scss,less等CSS預處理器

  這些方法每每有不少文件瀏覽器不能直接識別,須要二次處理後才能夠,此時webpack應允而生node

  WebPack能夠看作是模塊打包機react

    它作的事情是,分析你的項目結構,找到JavaScript模塊以及其它的一些瀏覽器不能直接運行的拓展語言(Scss,TypeScript等),並將其轉換和打包爲合適的格式供瀏覽器使用webpack

  Webpack的工做方式是:es6

    把你的項目當作一個總體,經過一個給定的主文件(如:index.js),Webpack將從這個文件開始找到你的項目的全部依賴文件,使用loaders處理它們,最後打包爲一個(或多個)瀏覽器可識別的JavaScript文件web

2.開始使用webpack正則表達式

  2.1 開始安裝webpacknpm

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

//全局安裝
npm install -g webpack
//安裝到你的項目目錄
npm install --save-dev webpack

  2.2 開始前準備

    2.2.1 在這個路徑的cmd中輸入npm init,自動生成package.json文件寫入項目的信息,若是不作正式使用能夠回車默認便可

    2.2.2 在本項目中安裝Webpack做爲依賴包

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

    2.2.3 回到以前的空文件夾,並在裏面建立兩個文件夾,app文件夾和public文件夾,app文件夾用來存放原始數據和咱們將寫的JavaScript模塊,public文件夾用來存放以後供瀏覽器讀取的文件(包括使用webpack打包生成的js文件以及一個index.html文件)。接下來咱們再建立三個文件:

  • index.html --放在public文件夾中;
  • Greeter.js-- 放在app文件夾中;
  • main.js-- 放在app文件夾中;

    

    在index.html文件中寫入最基礎的html代碼,它在這裏目的在於引入打包後的js文件(這裏咱們先把以後打包後的js文件命名爲bundle.js,以後咱們還會詳細講述)

<!-- index.html -->
<!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元素的函數,並依據CommonJS規範導出這個函數爲一個模塊:

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

    main.js文件中咱們寫入下述代碼,用以把Greeter模塊返回的節點插入頁面。

//main.js 
const greeter = require('./Greeter.js');
document.querySelector("#root").appendChild(greeter());

    2.2.4 正式使用webpack

  webpack能夠在終端中使用,在基本的使用方法以下:

# {extry file}出填寫入口文件的路徑,本文中就是上述main.js的路徑,
# {destination for bundled file}處填寫打包文件的存放路徑
# 填寫路徑的時候不用添加{}
webpack {entry file} {destination for bundled file}

  指定入口文件後,webpack將自動識別項目所依賴的其它文件,不過須要注意的是若是你的webpack不是全局安裝的,那麼當你在終端中使用此命令時,須要額外指定其在node_modules中的地址,繼續上面的例子,在終端中輸入以下命令

# webpack非全局安裝的狀況
node_modules/.bin/webpack app/main.js public/bundle.js

    運行完成後就會在public文件夾中自動生成bundle.js,被index.html引用成功!至此一個完整的小webpack項目結束

  有沒有以爲在cmd中輸入的webpack命名比較繁瑣,好的,這裏有較爲簡單的命令方法,但須要修改下配置文件package.json

{
  "name": "webpack-sample-project",
  "version": "1.0.0",
  "description": "Sample webpack project",
  "scripts": {
    "start": "webpack" // 修改的是這裏,JSON文件不支持註釋,引用時請清除
  },
  "author": "zhang",
  "license": "ISC",
  "devDependencies": {
    "webpack": "3.10.0"
  }
}

  以後想要啓動啓動webpack只需在對應的項目目錄下只需npm start效果就能完整的命令效果同樣

3.webpack 強大功能

  3.1 可調試

    通常經過打包後的文件,不容易找到出錯的地方,對應你寫的代碼的位置,配置了Source maps就能幫咱們解決這個問題,經過簡單的配置,webpack能夠幫咱們生成Source Maps,這爲咱們提供了一種對應的編譯文件與源文件方法,使得編譯後的代碼可讀性更高:配置devtool便可

devtool選項 配置結果
source-map 在一個單獨的文件中產生一個完整且功能徹底的文件。這個文件具備最好的source map,可是它會減慢打包速度;
cheap-module-source-map 在一個單獨的文件中生成一個不帶列映射的map,不帶列映射提升了打包速度,可是也使得瀏覽器開發者工具只能對應到具體的行,不能對應到具體的列(符號),會對調試形成不便;
eval-source-map 使用eval打包源文件模塊,在同一個文件中生成乾淨的完整的source map。這個選項能夠在不影響構建速度的前提下生成完整的sourcemap,可是對打包後輸出的JS文件的執行具備性能和安全的隱患。在開發階段這是一個很是好的選項,在生產階段則必定不要啓用這個選項;
cheap-module-eval-source-map 這是在打包文件時最快的生成source map的方法,生成的Source Map 會和打包後的JavaScript文件同行顯示,沒有列映射,和eval-source-map選項具備類似的缺點;

對小到中型的項目中,eval-source-map是一個很好的選項,再次強調你只應該開發階段使用它,咱們繼續對上文新建的webpack.config.js,進行以下配置:

module.exports = {
  devtool: 'eval-source-map',
  entry:  __dirname + "/app/main.js",
  output: {
    path: __dirname + "/public",
    filename: "bundle.js"
  }
}
方法構建速度更快,可是不利於調試,推薦在大型項目考慮時間成本時使用。
cheap-module-eval-source-map

  3.2 配置本地服務器

    這個本地服務器是基於node.js,須要將webpack-dev-server在項目根目錄下安裝

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

    devserver做爲webpack配置選項中的一項,如下是它的一些配置選項,更多配置可參考這裏

devserver的配置選項 功能描述
contentBase 默認webpack-dev-server會爲根文件夾提供本地服務器,若是想爲另一個目錄下的文件提供本地服務器,應該在這裏設置其所在目錄(本例設置到「public"目錄)
port 設置默認監聽端口,若是省略,默認爲」8080「
inline 設置爲true,當源文件改變時會自動刷新頁面
historyApiFallback 在開發單頁應用時很是有用,它依賴於HTML5 history API,若是設置爲true,全部的跳轉將指向index.html

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

  

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

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

  devServer: {
    contentBase: "./public",//本地服務器所加載的頁面所在的目錄
    historyApiFallback: true,//不跳轉
    inline: true//實時刷新
  } 
}

  在package.json中的scripts對象中添加以下命令,用以開啓本地服務器:

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack",
    "server": "webpack-dev-server --open"
  },

  在終端中輸入npm run server便可在本地的8080端口查看結果

  3.3 Loaders

    Loaders的功能就強大了,他能夠將不是js的文件類型轉爲js讓瀏覽器能夠識別

    好比說分析轉換scss爲css,或者把下一代的JS文件(ES6,ES7)轉換爲現代瀏覽器兼容的JS文件,對React的開發而言,合適的Loaders能夠把React的中用到的JSX文件轉換爲JS文件

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

  • test:一個用以匹配loaders所處理文件的拓展名的正則表達式(必須)
  • loader:loader的名稱(必須)
  • include/exclude:手動添加必須處理的文件(文件夾)或屏蔽不須要處理的文件(文件夾)(可選);
  • query:爲loaders提供額外的設置選項(可選)

  不過在配置loader以前,咱們把Greeter.js裏的問候消息放在一個單獨的JSON文件裏,並經過合適的配置使Greeter.js能夠讀取該JSON文件的值,各文件修改後的代碼以下:

在app文件夾中建立帶有問候信息的JSON文件(命名爲config.json)

{
  "greetText": "Hi there and greetings from JSON!"
}

更新後的Greeter.js  

var config = require('./config.json');

module.exports = function() {
  var greet = document.createElement('div');
  greet.textContent = config.greetText;
  return greet;
};

在看如何具體使用loader以前咱們先看看Babel是什麼?

  3.4 Babel

  Babel實際上是一個編譯JavaScript的平臺,它能夠編譯代碼幫你達到如下目的:

  • 讓你能使用最新的JavaScript代碼(ES6,ES7...),而不用管新標準是否被當前使用的瀏覽器徹底支持;
  • 讓你能使用基於JavaScript進行了拓展的語言,好比React的JSX;

  Babel的安裝與配置

    Babel實際上是幾個模塊化的包,其核心功能位於稱爲babel-core的npm包中,webpack能夠把其不一樣的包整合在一塊兒使用,對於每個你須要的功能或拓展,你都須要安裝單獨的包(用得最多的是解析Es6的babel-env-preset包和解析JSX的babel-preset-react包)。

// npm一次性安裝多個依賴模塊,模塊之間用空格隔開
npm install --save-dev babel-core babel-loader babel-preset-env babel-preset-react

webpack中配置Babel的方法以下:

module.exports = {
    entry: __dirname + "/app/main.js",//已屢次說起的惟一入口文件
    output: {
        path: __dirname + "/public",//打包後的文件存放的地方
        filename: "bundle.js"//打包後輸出文件的文件名
    },
    devtool: 'eval-source-map',
    devServer: {
        contentBase: "./public",//本地服務器所加載的頁面所在的目錄
        historyApiFallback: true,//不跳轉
        inline: true//實時刷新
    },
    module: {
        rules: [
            {
                test: /(\.jsx|\.js)$/,
                use: {
                    loader: "babel-loader",
                    options: {
                        presets: [
                            "env", "react"
                        ]
                    }
                },
                exclude: /node_modules/
            }
        ]
    }
};

如今你的webpack的配置已經容許你使用ES6以及JSX的語法了。繼續用上面的例子進行測試,不過此次咱們會使用React,記得先安裝 React 和 React-DOM

npm install --save react react-dom

接下來咱們使用ES6的語法,更新Greeter.js並返回一個React組件

//Greeter,js
import React, {Component} from 'react'
import config from './config.json';

class Greeter extends Component{
  render() {
    return (
      <div>
        {config.greetText}
      </div>
    );
  }
}

export default Greeter

修改main.js以下,使用ES6的模塊定義和渲染Greeter模塊

// main.js
import React from 'react';
import {render} from 'react-dom';
import Greeter from './Greeter';

render(<Greeter />, document.getElementById('root'));

從新使用npm start打包,若是以前打開的本地服務器沒有關閉,你應該能夠在localhost:8080下看到與以前同樣的內容,這說明reactes6被正常打包了。

Babel的配置

Babel其實能夠徹底在 webpack.config.js 中進行配置,可是考慮到babel具備很是多的配置選項,在單一的webpack.config.js文件中進行配置每每使得這個文件顯得太複雜,所以一些開發者支持把babel的配置選項放在一個單獨的名爲 ".babelrc" 的配置文件中。咱們如今的babel的配置並不算複雜,不過以後咱們會再加一些東西,所以如今咱們就提取出相關部分,分兩個配置文件進行配置(webpack會自動調用.babelrc裏的babel配置選項),以下:

module.exports = {
    entry: __dirname + "/app/main.js",//已屢次說起的惟一入口文件
    output: {
        path: __dirname + "/public",//打包後的文件存放的地方
        filename: "bundle.js"//打包後輸出文件的文件名
    },
    devtool: 'eval-source-map',
    devServer: {
        contentBase: "./public",//本地服務器所加載的頁面所在的目錄
        historyApiFallback: true,//不跳轉
        inline: true//實時刷新
    },
    module: {
        rules: [
            {
                test: /(\.jsx|\.js)$/,
                use: {
                    loader: "babel-loader"
                },
                exclude: /node_modules/
            }
        ]
    }
};
//.babelrc
{
  "presets": ["react", "env"]
}

到目前爲止,咱們已經知道了,對於模塊,Webpack能提供很是強大的處理功能,那那些是模塊呢。

一切皆模塊

Webpack有一個不可不說的優勢,它把全部的文件都都當作模塊處理,JavaScript代碼,CSS和fonts以及圖片等等經過合適的loader均可以被處理。

 

CSS

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

//安裝
npm install --save-dev style-loader css-loader
//使用
module.exports = {

   ...
    module: {
        rules: [
            {
                test: /(\.jsx|\.js)$/,
                use: {
                    loader: "babel-loader"
                },
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                use: [
                    {
                        loader: "style-loader"
                    }, {
                        loader: "css-loader"
                    }
                ]
            }
        ]
    }
};

接下來,在app文件夾裏建立一個名字爲"main.css"的文件,對一些元素設置樣式

/* main.css */
html {
  box-sizing: border-box;
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
}

*, *:before, *:after {
  box-sizing: inherit;
}

body {
  margin: 0;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

h1, h2, h3, h4, h5, h6, p, ul {
  margin: 0;
  padding: 0;
}

咱們這裏例子中用到的webpack只有單一的入口,其它的模塊須要經過 importrequireurl等與入口文件創建其關聯,爲了讓webpack能找到」main.css「文件,咱們把它導入」main.js 「中,以下

//main.js
import React from 'react';
import {render} from 'react-dom';
import Greeter from './Greeter';

import './main.css';//使用require導入css文件

render(<Greeter />, document.getElementById('root'));

上面的代碼說明webpack是怎麼把css當作模塊看待的,我們繼續看一個更加真實的css模塊實踐。

CSS module

CSS預處理器

插件(Plugins)

相關文章
相關標籤/搜索