前端面試之webpack篇

仍是之前同樣,有些概念面試可能會考,我都用*標記了出來,兩句話就總結清楚其他的地方若是你想了解webpack,就仔細看看,雖然本教程不能讓你webpack玩的很6,可是懂操做流程夠了。面試你通常問你webpack的原理,Loader的原理,你有用那些優化措施
前端開發已經模塊化,它改進了代碼庫的封裝和結構。打包工具已經成爲了一個項目必不可少的部分,
現在這兒有幾種可能的選擇,例如webpack,grunt,gulp等。
webpack由於他的功能和擴展性在過去的幾年中,受到很是大的歡迎。可是webpack的配置老是讓人以爲很困惑,
今天咱們將從一個空的配置文件逐步完成一個完整的設置進行打包文件。css

概念

clipboard.png

不像大多數的模塊打包機,webpack是收把項目看成一個總體,經過一個給定的的主文件,webpack將從這個文件開始找到你的項目的全部依賴文件,使用loaders處理它們,最後打包成一個或多個瀏覽器可識別的js文件html

install

首先添加咱們即將使用的包:前端

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

webpack是咱們須要的模塊打包機,webpack-dev-server用來建立本地服務器,監聽你的代碼修改,並自動刷新修改後的結果。這些是有關devServer的配置node

contentBase,  // 爲文件提供本地服務器
port, // 監聽端口,默認8080
inline, // 設置爲true,源文件發生改變自動刷新頁面
historyApiFallback  // 依賴HTML5 history API,若是設置爲true,全部的頁面跳轉指向index.html
devServer:{
    contentBase: './src' // 本地服務器所加載的頁面所在的目錄
    historyApiFallback: true, // 不跳轉
    inline: true // 實時刷新
}
而後咱們在根目錄下建立一個'webpack.config.js',在'package.json'添加兩個命令用於本地開發和生產發佈
    

"scripts": {
            "start": "webpack-dev-server",
            "build": "webpack"
        }

在使用webpack命令的時候,他將接受webpack的配置文件,除非咱們使用其餘的操做webpack

entry

entry: 用來寫入口文件,它將是整個依賴關係的根web

var baseConfig = {
        entry: './src/index.js'
    }

當咱們須要多個入口文件的時候,能夠把entry寫成一個對象面試

var baseConfig = {
        entry: {
            main: './src/index.js'
        }
    }

我建議使用後面一種方法,由於他的規模會隨你的項目增大而變得繁瑣正則表達式

output

output: 即便入口文件有多個,可是隻有一個輸出配置typescript

var path = require('path')
    var baseConfig = {
        entry: {
            main: './src/index.js'
        },
        output: {
            filename: 'main.js',
            path: path.resolve('./build')
        }
    }
    module.exports = baseConfig

若是你定義的入口文件有多個,那麼咱們須要使用佔位符來確保輸出文件的惟一性npm

output: {
        filename: '[name].js',
        path: path.resolve('./build')
    }

現在這麼少的配置,就可以讓你運行一個服務器並在本地使用命令npm start或者npm run build來打包咱們的代碼進行發佈

Loader

loader的做用
一、實現對不一樣格式的文件的處理,好比說將scss轉換爲css,或者typescript轉化爲js
二、轉換這些文件,從而使其可以被添加到依賴圖中
loader是webpack最重要的部分之一,經過使用不一樣的Loader,咱們可以調用外部的腳本或者工具,實現對不一樣格式文件的處理,loader須要在webpack.config.js裏邊單獨用module進行配置,配置以下:

test: 匹配所處理文件的擴展名的正則表達式(必須)
    loader: loader的名稱(必須)
    include/exclude: 手動添加處理的文件,屏蔽不須要處理的文件(可選)
    query: 爲loaders提供額外的設置選項
    ex: 
        var baseConfig = {
            // ...
            module: {
                rules: [
                    {
                        test: /*匹配文件後綴名的正則*/,
                        use: [
                            loader: /*loader名字*/,
                            query: /*額外配置*/
                        ]
                    }
                ]
            }
        }

要是loader工做,咱們須要一個正則表達式來標識咱們要修改的文件,而後有一個數組表示
咱們表示咱們即將使用的Loader,固然咱們須要的loader須要經過npm 進行安裝。例如咱們須要解析less的文件,那麼webpack.config.js的配置以下:

var baseConfig = {
                entry: {
                    main: './src/index.js'
                },
                output: {
                    filename: '[name].js',
                    path: path.resolve('./build')
                },
                devServer: {
                    contentBase: './src',
                    historyApiFallBack: true,
                    inline: true
                },
                module: {
                    rules: [
                        {
                            test: /\.less$/,
                            use: [
                                {loader: 'style-loader'},
                                {loader: 'css-loader'},
                                {loader: 'less-loader'}
                            ],
                            exclude: /node_modules/
                        }
                    ]
                }
            }

這裏介紹幾個經常使用的loader:
babel-loader: 讓下一代的js文件轉換成現代瀏覽器可以支持的JS文件。
babel有些複雜,因此大多數都會新建一個.babelrc進行配置
css-loader,style-loader:兩個建議配合使用,用來解析css文件,可以解釋@import,url()若是須要解析less就在後面加一個less-loader
file-loader: 生成的文件名就是文件內容的MD5哈希值並會保留所引用資源的原始擴展名
url-loader: 功能相似 file-loader,可是文件大小低於指定的限制時,能夠返回一個DataURL事實上,在使用less,scss,stylus這些的時候,npm會提示你差什麼插件,差什麼,你就安上就好了

Plugins

plugins和loader很容易搞混,說都是外部引用有什麼區別呢? 事實上他們是兩個徹底不一樣的東西。這麼說loaders負責的是處理源文件的如css、jsx,一次處理一個文件。而plugins並非直接操做單個文件,它直接對整個構建過程起做用下面列舉了一些咱們經常使用的plugins和他的用法
ExtractTextWebpackPlugin: 它會將入口中引用css文件,都打包都獨立的css文件中,而不是內嵌在js打包文件中。下面是他的應用

var ExtractTextPlugin = require('extract-text-webpack-plugin')
        var lessRules = {
            use: [
                {loader: 'css-loader'},
                {loader: 'less-loader'}
            ]
        }
        
        var baseConfig = {
            // ... 
            module: {
                rules: [
                    // ...
                    {test: /\.less$/, use: ExtractTextPlugin.extract(lessRules)}
                ]
            },
            plugins: [
                new ExtractTextPlugin('main.css')
            ]
        }

HtmlWebpackPlugin:
做用: 依據一個簡單的index.html模版,生成一個自動引用你打包後的js文件的新index.html

var HTMLWebpackPlugin = require('html-webpack-plugin')
            var baseConfig = {
                // ...
                plugins: [
                    new HTMLWebpackPlugin()
                ]
            }

HotModuleReplacementPlugin: 它容許你在修改組件代碼時,自動刷新實時預覽修改後的結果注意永遠不要在生產環境中使用HMR。這兒說一下通常狀況分爲開發環境,測試環境,生產環境。
用法如 new webpack.HotModuleReplacementPlugin()

webapck.config.js的所有內容
    

const webpack = require("webpack")
        const HtmlWebpackPlugin = require("html-webpack-plugin")
        var ExtractTextPlugin = require('extract-text-webpack-plugin')
        var lessRules = {
            use: [
                {loader: 'css-loader'},
                {loader: 'less-loader'}
            ]
        }
        module.exports = {
            entry: {
                    main: './src/index.js'
                },
                output: {
                    filename: '[name].js',
                    path: path.resolve('./build')
                },
                devServer: {
                    contentBase: '/src',
                    historyApiFallback: true,
                    inline: true,
                    hot: true
                },
                module: {
                    rules: [
                        {test: /\.less$/, use: ExtractTextPlugin.extract(lessRules)}
                    ]
                },
                plugins: [
                new ExtractTextPlugin('main.css')
            ]
        }

產品階段的構建

目前爲止,在開發階段的東西咱們已經基本完成了。可是在產品階段,還須要對資源進行別的
處理,例如壓縮,優化,緩存,分離css和js。首先咱們來定義產品環境

var ENV = process.env.NODE_ENV
    var baseConfig = {
        // ... 
        plugins: [
            new webpack.DefinePlugin({
                'process.env.NODE_ENV': JSON.stringify(ENV)
            })
        ]
    }

而後還須要修改咱們的script命令

"scripts": {
            "start": "NODE_ENV=development webpack-dev-server",
            "build": "NODE_ENV=production webpack"
        }

process.env.NODE_ENV 將被一個字符串替代,它運行壓縮器排除那些不可到達的開發代碼分支。
當你引入那些不會進行生產的代碼,下面這個代碼將很是有用。

if (process.env.NODE_ENV === 'development') {
            console.warn('這個警告會在生產階段消失')
        }

優化插件

下面介紹幾個插件用來優化代碼
OccurenceOrderPlugin: 爲組件分配ID,經過這個插件webpack能夠分析和優先考慮使用最多 的模塊,而後爲他們分配最小的ID
UglifyJsPlugin: 壓縮代碼
下面是他們的使用方法
var baseConfig = {

// ...
 new webpack.optimize.OccurenceOrderPlugin()
 new webpack.optimize.UglifyJsPlugin()

}
而後在咱們使用npm run build會發現代碼是壓縮的

總結

webpack的配置文件的複雜度,依賴於你項目的須要。當心的運用他們。由於隨着項目的增加,它們會變得很難馴服。內容有點多,事實上總結起來也不是特別多,也就Loader,plugins。其餘的地方都比較簡單。這篇文章大概花了我三天的時間,網上看各類教程,而後看官網,真挺累的。這兒寫完我就去睡覺

相關文章
相關標籤/搜索