webpack使用 入門詳解

1: 閱讀前先花點時間看這裏吧

閱讀本文之前,先看下面這個webpack的配置文件,如果每一項你都懂,那本文能帶給你的收穫也許就比較有限,你可以快速瀏覽或直接跳過;如果你和十天前的我一樣,對很多選項存在着疑惑,那花一段時間慢慢閱讀本文,你的疑惑一定一個一個都會消失;如果你以前沒怎麼接觸過Webpack,而你又你對webpack感興趣,那麼動手跟着本文中那個貫穿始終的例子寫一次,寫完以後你會發現你已明明白白的走進了Webpack的大門。

// 一個常見的`webpack`配置文件
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
        entry:{
            app:'./src/main.js',//已多次提及的唯一入口文件
        },
        // 或者 entry: __dirname + "/app/main.js", 
        output: {
            path: __dirname + "/build",
            filename: "bundle-[hash].js"
        },
        devtool: 'none',
        devServer: {
            contentBase: "./public", //本地服務器所加載的頁面所在的目錄
            historyApiFallback: true, //不跳轉
            inline: true,
            hot: true
        },
        module: {
            rules: [{
                    test: /(\.jsx|\.js)$/,
                    use: {
                        loader: "babel-loader"
                    },
                    exclude: /node_modules/
                }, {
                    test: /\.css$/,
                    use: ExtractTextPlugin.extract({
                        fallback: "style-loader",
                        use: [{
                            loader: "css-loader",
                            options: {
                                modules: true,
                                localIdentName: '[name]__[local]--[hash:base64:5]'
                            }
                        }, {
                            loader: "postcss-loader"
                        }],
                    })
                }
            }
        ]
    },
    plugins: [
        new webpack.BannerPlugin('版權所有,翻版必究'),
        new HtmlWebpackPlugin({
            template: __dirname + "/app/index.tmpl.html" //new 一個這個插件的實例,並傳入相關的參數
        }),
        new webpack.optimize.OccurrenceOrderPlugin(),
        new webpack.optimize.UglifyJsPlugin(),
        new ExtractTextPlugin("style.css")
    ]
};
2: webpack是什麼,爲什麼要使用它
2.1: 什麼是 webpack

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

其實Webpack和另外兩個並沒有太多的可比性,Gulp/Grunt是一種能夠優化前端的開發流程的工具,而WebPack是一種模塊化的解決方案,不過Webpack的優點使得Webpack在很多場景下可以替代Gulp/Grunt類的工具。

Grunt和Gulp的工作方式是:在一個配置文件中,指明對某些文件進行類似編譯,組合,壓縮等任務的具體步驟,工具之後可以自動替你完成這些任務。
在這裏插入圖片描述

Webpack的工作方式是:把你的項目當做一個整體,通過一個給定的主文件(如:index.js),Webpack將從這個文件開始找到你的項目的所有依賴文件,使用loaders處理它們,最後打包爲一個(或多個)瀏覽器可識別的JavaScript文件。
在這裏插入圖片描述

2.2: 爲什麼要使用它

現今的很多網頁其實可以看做是功能豐富的應用,它們擁有着複雜的JavaScript代碼和一大堆依賴包。爲了簡化開發的複雜度,前端社區涌現出了很多好的實踐方法。

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

這些改進確實大大的提高了我們的開發效率,但是利用它們開發的文件往往需要進行額外的處理才能讓瀏覽器識別,而手動處理又是非常繁瑣的,這就爲WebPack類的工具的出現提供了需求。

3: 開始使用 webpack

初步瞭解了Webpack工作方式後,我們一步步的開始學習使用Webpack。

3.1: 安裝

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

//全局安裝
npm install -g webpack
//安裝到你的項目目錄
npm install --save-dev webpack
3.2: 使用前準備
  1. 在上述練習文件夾中創建一個package.json文件,這是一個標準的npm說明文件,裏面蘊含了豐富的信息,包括當前項目的依賴模塊,自定義的腳本任務等等。在終端中使用npm init命令可以自動創建這個package.json文件
 npm init

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

  1. package.json文件已經就緒,我們在本項目中安裝Webpack作爲依賴包
// 安裝Webpack
cnpm install --save-dev webpack
  1. 回到之前的空文件夾,並在裏面創建兩個文件夾,src文件夾和dist文件夾,src文件夾用來存放原靜態資源,dist文件夾用來存放之後供瀏覽器讀取的文件(包括使用webpack打包生成的js)。接下來我們再創建三個文件:
  • css --放在src文件夾中;
  • images-- 放在src文件夾中;
  • js-- 放在src文件夾中;
  • index.html–寫基本的html結構
  • main–寫main入口js代碼
    此時目錄結構如下:
    在這裏插入圖片描述
    我們在index.html文件中寫入最基礎的html代碼,它在這裏目的在於引入打包後的js文件(這裏我們先把之後打包後的js文件命名爲bundle.js,之後我們還會詳細講述)。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script src="../dist/bundle.js"></script>
    <ul>
        <li>11*10</li>
        <li>21*10</li>
        <li>31*10</li>
    </ul>
</body>
</html>

main.js文件中我們寫入下述代碼。

// 由於 ES6的代碼,太高級了,瀏覽器解析不了,所以,這一行執行會報錯
import $ from 'jquery';

$(function(){
    $('li:odd').css('backgroundColor','red');
    $('li:even').css('backgroundColor','yellow');
});

直接在頁面上引用main.js會報錯,因爲瀏覽器不認識 import 這種 es6 高級的JS語法,需要使用webpack進行處理,webpack默認會把這種高級的語法轉換爲低級的瀏覽器能識別的語法;

需要安裝 webpack-cli。

npm install webpack webpack-cli --save-dev
4: 正式使用 webpack

因爲上面用了 jQuery,所以我們需要安裝下

cnpm install jquery --save

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

webpack src/js/main.js --output dist/bundle.js

運行完此時可以看到 dist/bundle.js 會自動生成編譯好的代碼,可以看出webpack編譯了main.js 現在右鍵打開index.html,可以看到如下結果

在這裏插入圖片描述
在這裏插入圖片描述

有沒有很激動,已經成功的使用Webpack打包了一個文件了。不過在終端中進行復雜的操作,其實是不太方便且容易出錯的,接下來看看Webpack的另一種更常見的使用方法。

5: 通過配置使用 webpack 啓動項目

Webpack擁有很多其它的比較高級的功能(比如說本文後面會介紹的loaders和plugins),這些功能其實都可以通過命令行模式實現,但是正如前面提到的,這樣不太方便且容易出錯的,更好的辦法是定義一個配置文件,這個配置文件其實也是一個簡單的JavaScript模塊,我們可以把所有的與打包相關的信息放在裏面。

繼續上面的例子來說明如何寫這個配置文件,在當前練習文件夾的根目錄下新建一個名爲webpack.config.js的文件,我們在其中寫入如下所示的簡單配置代碼,目前的配置主要涉及到的內容是入口文件路徑和打包後文件的存放路徑。

// 導入處理路徑的模塊
const path = require('path')

// 導出一個配置對象,將來webpack在啓動的時候,會默認來查找webpack.config.js,並讀取這個文件中導出的配置對象,來進行打包處理
module.exports = {
    entry:{
        app:'./src/main.js'
    },
    output: { // 配置輸出選項
        path:path.resolve(__dirname, 'dist'), // 配置輸出的路徑
        filename: 'bundle.js' // 配置輸出的文件名
    }
}

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

有了這個配置之後,再打包文件,只需在終端裏運行webpack(非全局安裝需使用node_modules/.bin/webpack)命令就可以了,這條命令會自動引用webpack.config.js文件中的配置選項,示例如下:

在這裏插入圖片描述

又學會了一種使用Webpack的方法,這種方法不用管那煩人的命令行參數,有沒有感覺很爽。如果我們可以連webpack(非全局安裝需使用node_modules/.bin/webpack)這條命令都可以不用,那種感覺會不會更爽~,繼續看下文。

6: 使用更快捷方式執行 webpack

在命令行中輸入命令需要代碼類似於node_modules/.bin/webpack這樣的路徑其實是比較煩人的,不過值得慶幸的是npm可以引導任務執行,對npm進行配置後可以在命令行中使用簡單的npm start命令來替代上面略微繁瑣的命令。在package.json中對scripts對象進行相關設置即可,設置方法如下。

{
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack"	// 修改的是這裏,JSON文件不支持註釋,引用時請清除
  },
}

注:package.json中的script會安裝一定順序尋找命令對應位置,本地的node_modules/.bin路徑就在這個尋找清單中,所以無論是全局還是局部安裝的Webpack,你都不需要寫前面那指明詳細的路徑了。

npm的start命令是一個特殊的腳本名稱,其特殊性表現在,在命令行中使用npm start就可以執行其對於的命令,如果對應的此腳本名稱不是start,想要在命令行中運行時,需要這樣用npm run {script name}如npm run build,我們在命令行中輸入npm start試試,輸出結果如下:
在這裏插入圖片描述

現在只需要使用npm start就可以打包文件了,有沒有覺得webpack也不過如此嘛,不過不要太小瞧webpack,要充分發揮其強大的功能我們需要修改配置文件的其它選項,一項項來看。

7: 使用 webpack 構建本地服務器

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

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如下所示

devServer: {
    contentBase: "./dist",//本地服務器所加載的頁面所在的目錄
    hot:true,
    inline: true//實時刷新
} 
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack",
    "server": "webpack-dev-server --open --contentBase src"	// 修改的是這裏,JSON文件不支持註釋,引用時請清除
  },

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

注:需要修改 index.html 下面的 bundle.js路徑爲

在這裏插入圖片描述

8: 管理資源

注: webpack 只能識別 JS 文件,其他外部文件需要 安裝對應的 loader 文件去做解析

8.1: 加載 css

爲了在 JavaScript 模塊中 import 一個 CSS 文件,你需要安裝 style-loader 和 css-loader,並在 module 配置 中添加這些 loader:

cnpm install --save-dev style-loader css-loader

webpack.config.js

module: {// 用來配置第三方loader模塊的
	rules: [{// 文件的匹配規則
		test: /.css$/,
		use: [//處理css文件的規則
			'style-loader',
			'css-loader'
		]
	}]
}

webpack 根據正則表達式,來確定應該查找哪些文件,並將其提供給指定的 loader。在這個示例中,所有以 .css 結尾的文件,都將被提供給 style-loader 和 css-loader。

我們嘗試一下,通過在項目中添加一個新的 index.css 文件,並將其 import 到我們的 index.js 中:

html body {
	background: #666;
	padding: 50px;
}

main.js 導入css文件

import './css/index.css';

現在運行 npm run server 命令:就可以看到 css 設置的樣式
在這裏插入圖片描述

8.2: 加載 less /sass

less / sass 的 使用 跟 css 類似,先 npm 安裝

cnpm install less-loader less -D
cnpm install sass-loader node-sass -save-dev

在配置 webpack.config.js 匹配規則

module: { // 用來配置第三方loader模塊的
    rules: [
        {
            test: /\.less$/,
            use: ['style-loader', 'css-loader', 'less-loader']
        }, //處理less文件的規則
        {
            test: /\.scss$/,
            use: ['style-loader', 'css-loader', 'sass-loader']
        }, //處理scss文件的規則
    ]
}

index.less

 html{
   body{
        background-color: hotpink;
    }
}

index.scss

 html{
   body{
        color: goldenrod;
    }
}

main.js

import './css/index.less';
import './css/index.sass';

運行 npm run server 命令即可看下效果
在這裏插入圖片描述

8.3: 加載 images 圖片

先 npm 安裝圖片的 loader

cnpm install --save-dev file-loader

在配置 webpack.config.js 匹配規則

module: { // 用來配置第三方loader模塊的
	rules: [
		{
			test: /\.(png|svg|jpg|gif)$/,
             use: [
             	'file-loader'
             ]
         }
    ]
}    

src 文件夾下images 文件下,添加一張圖片,在 index.html 頁面添加 div設置 id 爲 img

在 index.css 文件中設置背景圖樣式:如下

#img{
  background-image: url('../images/八神庵.png');
  width: 200px;
  height: 200px;
  background-color: bisque;
}

運行 npm run server 命令即可看下效果
在這裏插入圖片描述

8.4: 加載 font 字體

那麼,像字體這樣的其他資源如何處理呢?file-loader 和 url-loader 可以接收並加載任何文件,然後將其輸出到構建目錄。這就是說,我們可以將它們用於任何類型的文件,也包括字體。讓我們更新 webpack.config.js 來處理字體文件:

webpack.config.js

module: {
	rules: [
        {
         	test: /\.(woff|woff2|eot|ttf|otf)$/,
         	use: [
           		'file-loader'
         	]
       	}
    ]
} 

在項目中添加一些字體文件:
在這裏插入圖片描述
main.js 導入 font.css 文件

import './css/font.css';

配置好 loader 並將字體文件放在合適的位置後,你可以通過一個 @font-face 聲明將其混合。本地的 url(…) 指令會被 webpack 獲取處理,就像它處理圖片一樣:在 index.css 文件中

@font-face {
  font-family: 'MyFont';
  src: url('../fonts/MiFie-Web-Font.woff') format('woff'),
    url('../fonts/MiFie-Web-Font.svg') format('svg');
  font-weight: 600;
  font-style: normal;
}
/* 設置使用字體爲 MyFont */
html body {
  font-size: 50px;
  font-family: 'MyFont';
}

在頁面添加一個標籤,類名爲字體圖標類名,如下

 <span class="icon-meiyuan"></span>

運行 npm run server 命令即可看下效果
在這裏插入圖片描述

9: bable 的使用

Babel其實是一個編譯JavaScript的平臺,它可以編譯代碼幫你達到以下目的:

  • webpack默認只能處理部分ES6語法,一些更高級的ES6或ES7語法,需要藉助第三方的loader處理,轉爲低級的語法後,而不用管新標準是否被當前使用的瀏覽器完全支持;,把結果交給webpack打包到bundle.js中。
  • 讓你能使用基於JavaScript進行了拓展的語言,比如React的JSX;
9.1: Babel的安裝與配置

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

我們先來一次性安裝這些依賴包

npm install --save-dev "babel-loader@^8.0.0-beta" @babel/core @babel/preset-env

在 webpack.config.js 配置對象中,需要添加 babel-loader 到 module 的 loaders 列表中,像下面這樣:

module: {
  rules: [
    {
      test: /\.js$/,
      exclude: /(node_modules|bower_components)/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env']
        }
      }
    }
  ]
}

在項目根目錄中添加.babelrc文件,並修改這個配置文件如下

{
  "presets":["@babel/preset-env"],
  "plugins":["@babel/plugin-transform-runtime"]
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章