webpack的一點(diǎn)介紹

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

Webpack 把任何一個(gè)文件都看成一個(gè)模塊,模塊間可以互相依賴(require or import),webpack 的功能是把相互依賴的文件打包在一起。webpack 本身只能處理原生的 JavaScript 模塊,但是 loader 轉(zhuǎn)換器可以將各種類型的資源轉(zhuǎn)換成 JavaScript 模塊。這樣,任何資源都可以成為 Webpack 可以處理的模塊。同時(shí),webpack還有豐富的插件 plugin,可以完成例如js,css的壓縮,公共依賴模塊的提取和注入,甚至利用模板對(duì) html 進(jìn)行動(dòng)態(tài)拼接等功能。

同時(shí),webpack 使用commonjs規(guī)范(require),支持es6語(yǔ)法(import)的編譯,可以方便的抽離vue組件,這成為我們選擇它的重要理由。

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

 

對(duì)webpack工作方式直觀的理解(官網(wǎng)小示例)

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

import: es6 引入依賴的方式,還可以用commonjs 規(guī)范的require

var bar  = require('./bar')

module.exports: commonjs規(guī)范中對(duì)外暴露本模塊接口的方式。每個(gè)模塊內(nèi)部,都有一個(gè)module對(duì)象,代表當(dāng)前模塊,module對(duì)象包含module.id,module.filename,module.exports等信息

entry: 編譯的入口js文件,即需要處理的js文件(所有的其他模塊包括image,css,vue組件,html模板等都是通過(guò)js依賴引入進(jìn)來(lái)的)

output: 編譯的出口js文件,即經(jīng)過(guò)打包其他資源、合并、壓縮等處理之后生成的js文件

本示例中因?yàn)?app.js 依賴 bar.js ,所以打包之后的 bundle.js 可以理解為app.js和bar.js合并后的js

命令行工具中運(yùn)行:wepack 即編譯成功

 


 

實(shí)際項(xiàng)目中的webpack解析

本項(xiàng)目已支持功能

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

 1 對(duì)less編譯
 2 對(duì)js es6語(yǔ)法支持
 3 編譯.vue組件,并自動(dòng)內(nèi)聯(lián)組件樣式
 4 圖片打包,包括對(duì)html內(nèi)圖片處理(利用html-loader和es6字符串模板),對(duì)小圖片生成base64
 5 利用htmlWebpackPlugin動(dòng)態(tài)拼接html 的公共部分和內(nèi)容部分,引入相應(yīng)css/js資源,并構(gòu)建到指定目錄, 對(duì)ejs模板支持
 6 對(duì)js內(nèi)依賴的css分離并壓縮
 7 對(duì)js引用的公共模塊抽取分離成單獨(dú)文件
 8 區(qū)分開(kāi)發(fā)環(huán)境和生產(chǎn)環(huán)境
 9 js 壓縮
10 靜態(tài)文件(css/js/img)hash版本支持
11 清除目標(biāo)文件目錄
12 eslint支持并實(shí)現(xiàn)自動(dòng)修復(fù)部分問(wèn)題
13 vue接口請(qǐng)求axios支持
14 熱更新,自動(dòng)編譯并刷新瀏覽器

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

 

項(xiàng)目目錄結(jié)構(gòu)

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

  |__ html
        |__ dist
              |__ income.html
              |__ index.html
        |__ src
              |__ income
                |__ income.ejs
                |__ income.js
              |__ index
                |__ index.ejs
                |__ index.js
              |__ layouts
                |__ footer.ejs
                |__ header.ejs
                |__ layout.ejs
                |__ layout.js
                |__ side-menu.e
                |__ top-nav.ejs
  |__ dist
        |__ css
        |__ img
        |__ js
              |__ income.js
              |__ index.js
              |__ manifest.js
              |__ vendors.js
  |__ src
        |__ css
        |__ img
        |__ js
              |__ component
                |__ App.vue
              |__ income.js
              |__ index.js
              |__ lib
                |__ axios.min.js
                |__ layer.js
                |__ vue.js
                |__ vue.min.js
  |__ mock
  |__ node_modules
  |__ webpack-config
        |__ .eslintrc.dev.js
        |__ .eslintrc.js
        |__ postcss.config.js
        |__ resolve.config.js
  |__ package.json
  |__ .babelrc
  |__ .eslintrc.js

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

 

一. entry介紹

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

var entries = getEntry('./src/**/*.js') // 獲得入口js文件entries.vendors = ['vue','axios']

module.exports = {     /* 輸入文件 */
    entry: entries}

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

通常我們的項(xiàng)目中有大量的js入口文件,基本一個(gè)功能頁(yè)面有一個(gè)js,這時(shí)我們的 entry 文件為一個(gè)對(duì)象格式

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

'./src/js/income.js''./src/js/index.js'
  vendors: [ 'vue', 'axios'

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

key 值為對(duì)應(yīng)模塊的別名,webpack會(huì)依次處理這些模塊。

vendors 為公共模塊,這里我們把vue, axios設(shè)置為公共模塊,供下面進(jìn)行提取公共模塊操作。

 

之所以可以直接寫(xiě)vue, axios,是因?yàn)槲覀冊(cè)?nbsp;alias 里設(shè)置了別名:

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

var path = require('path')

module.exports = {  // 模塊別名的配置,為了使用方便,一般來(lái)說(shuō)所有模塊都是要配置一下別名的  alias: {    'vue': path.resolve(__dirname, '../src/js/lib/vue.min.js'),    'axios': path.resolve(__dirname, '../src/js/lib/axios.min.js')
  }
}

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

 

這里的 path.resolve 作用是把相對(duì)路徑轉(zhuǎn)為絕對(duì)路徑,假設(shè)我項(xiàng)目建在d:/demo 目錄下,

_dirname: d:\demo

path.resolve(__dirname, '../src/js/lib/vue.min.js'): d:\demo\src\js\lib\vue.min.js

 

getEntry() 為獲取文件路徑的自定義函數(shù):

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

var glob = require('glob')

 entries =
        (entry.indexOf('layouts') == -1 && entry.indexOf('lib') == -1==

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

通常webpack的entry入口文件,是功能性頁(yè)面的js,對(duì)于js庫(kù)等文件不需要列入入口文件進(jìn)行處理。所以這里對(duì)lib文件夾進(jìn)行了排除。layouts文件夾為獲取html路徑時(shí)需要排除的文件路徑。

 

二. output介紹

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

module.exports = {
    output: {        /* 輸出目錄,沒(méi)有則新建 */
        path: path.resolve(__dirname, './dist'),        /* 靜態(tài)目錄,可以直接從這里取文件 */
        publicPath: 'http://www.xxx.com/dist/',        /* 文件名 */
        filename: 'js/[name].js?v=[chunkhash:8]'
    }
}

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

 publicPath: 如果有這項(xiàng),則html中的引用的js路徑會(huì)加上publicPath,即 http://www.xxx.com/dist/js/[name].js?v=[chunkhash:8]

 filename: 這里可以自定義輸出后的文件名,加上版本號(hào)

  [name] :輸入模塊的別名

  [chunkhash] : 模塊的hash值,":8"代表保留8位hash值

  [hash] : 整個(gè)編譯環(huán)境的hash值

hash和chunkhash具體區(qū)別請(qǐng)看這里

 

三. module介紹

loaders: webpack利用各種loader來(lái)把不同格式的文件封裝成模塊加載到j(luò)s內(nèi),比如css-loader, vue-loader

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

-+/\.css$/--         "style-loader"-         "css-loader?modules=true"
+++           loader: "style-loader"
+++           loader: "css-loader"++             modules: ++/\.jsx$/"babel-loader",

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

 

eslint-loader

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

module: {
    rules: [
           {
                test: /\.js$/,
                enforce: 'pre',
                loader: 'eslint-loader',
                include: path.resolve(__dirname, './src/js/**/*.js'),
                exclude: ['./src/js/lib','./src/js/component'],
                options: {
                    fix: true
                }
            }  
    ]          
}

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

目的是 對(duì)js進(jìn)行代碼風(fēng)格和語(yǔ)法的校驗(yàn)

enforce: 注意這是webpack v2的變動(dòng),v1是 preLoaders。設(shè)置為pre表示對(duì)js的校驗(yàn)在編譯之前進(jìn)行,我們只負(fù)責(zé)自己寫(xiě)的js 語(yǔ)法和規(guī)范沒(méi)有問(wèn)題即可,編譯后的代碼什么樣都不管。

通常我們只對(duì)自己寫(xiě)的js進(jìn)行校驗(yàn),類庫(kù)和包里的js無(wú)需校驗(yàn)。include即聲明我們對(duì)哪些文件進(jìn)行校驗(yàn),相反,exclude是排除校驗(yàn)?zāi)男┪募?/span>

fix:true 即在編譯時(shí)自動(dòng)修復(fù)代碼風(fēng)格和語(yǔ)法問(wèn)題

 

babel-loader

{
    test: /\.js$/,
    loader: 'babel-loader',
    exclude: ['node_modules','./src/js/lib','./src/js/component']
}

es6語(yǔ)法目前很多瀏覽器不支持,我們需要將其轉(zhuǎn)化為大部分瀏覽器支持的es5語(yǔ)法,這就需要babel-loader

 

css-loader style-loader post-loader less-loader

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

{   
    test: /\.css$/, 
    use: ['style-loader', 'css-loader', 'postcss-loader']
},
{
    test: /\.less$/,
    use: ExtractTextPlugin.extract(['css-loader','postcss-loader','less-loader'])
}

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

對(duì)于有多個(gè)loader時(shí),webpack v2也廢棄了v1的 " !" 連接,改為數(shù)組形式,且不能省略 " -loader " 以免造成名稱混亂意思模糊,執(zhí)行順序?yàn)閺挠业阶?/p>

postcss-loader為集合處理css各種問(wèn)題的平臺(tái),其上面有各種插件來(lái)處理css,我們這里只用到了autoprefixer插件,后面插件部分會(huì)詳解

style-loader:可以將css以style內(nèi)聯(lián)方式嵌入到html頁(yè)面

ExtractTextPlugin:提取css, 后面插件部分會(huì)進(jìn)行詳解

 

file-loader url-loader 處理圖片

{
    test: /\.(png|jpg|gif)$/,
    loader: 'url-loader?limit=5120&name=img/[name].[ext]?v=[hash:8]'}

webpack中處理圖片用file-loader,但url-loader有個(gè)好處,它可以把小圖片轉(zhuǎn)化成base64格式,其他的大圖片再用file-loader處理,這里的limit即為臨界值,這里定義小于5k圖片轉(zhuǎn)成base64格式,大于5k的用file-loader處理。

name: 可以重新定義處理后的圖片并加上版本值。

 

 四. 插件plugin 

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

module: {},
plugins: [        new ExtractTextPlugin('css/[name].css?v=[contenthash:6]'),        new webpack.LoaderOptionsPlugin({
            options: {
                eslint: require( './webpack-config/.eslintrc.js'),
                postcss: require( './webpack-config/postcss.config.js')
            },
        })
    ]

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

 

插件可以補(bǔ)充loader的功能,對(duì)其進(jìn)行豐富完善,webpack聲明插件的方式可以像上面的寫(xiě)法也可以如下方式:

module.exports.plugins.push(new htmlWebpackPlugin())

 亦或

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

module.exports.plugins = module.exports.plugins.concat([        //壓縮css代碼
        new OptimizeCssAssetsPlugin({
            assetNameRegExp: /\.css/g,
            cssProcessor: require('cssnano'),
            cssProcessorOptions: { discardComments: {removeAll: true } },
            canPrint: true
        }),        //壓縮JS代碼
        new webpack.optimize.UglifyJsPlugin({
            output: {
                comments: false, // 去掉注釋內(nèi)容            }
        })
    ])

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

通常后兩種寫(xiě)法用于動(dòng)態(tài)的使用插件。

 

extract-text-webpack-plugin 插件

默認(rèn)情況下,js依賴引入css,編譯后,css被加在js中,如果我們想把css提取出一個(gè)單獨(dú)的文件,可以使用這個(gè)插件,并可以對(duì)提取出的css進(jìn)行自定義命名和加版本hash值

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

income.js中依賴income.less

如果不使用extractTextPlugin,編譯后的目錄結(jié)構(gòu)為

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

查看income.js,發(fā)現(xiàn)css被引入在js之中,模塊id為16

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

再看下webpack sourcemap下的income.less,css-loader已經(jīng)將此文件編譯成對(duì)外暴露的模塊形式,模塊id為16

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

使用extractTextPlugin插件后

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

income.js依賴的income.less被單獨(dú)提出,income.js中引入的模塊16發(fā)現(xiàn)提示 removed by extract-text-webpack-plugin,再看下此時(shí)的income.less

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

提示 removed by extract-text-webpack-plugin , 說(shuō)明此插件已經(jīng)順利的將js中的css提取成單文件形式

同時(shí)發(fā)現(xiàn)html中已插入income.css

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

這個(gè)是style-loader起的作用

 

LoaderOptionsPlugin插件

加載插件的配置項(xiàng),比如eslint的語(yǔ)法配置,postcss的插件配置

 

optimize-css-assets-webpack-plugin 插件

壓縮css文件,對(duì)從js中提取出的css文件亦有效

注意:此插件是在css被提取出來(lái)加了hash值后進(jìn)行處理,如果css文件提出來(lái)后被命名為  css/[name].css?v=[contenthash:8] 形式,插件的使用如下

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

new OptimizeCssAssetsPlugin({
            assetNameRegExp: /\.css/g,  //注意不要寫(xiě)成 /\.css$/g, 否則匹配不到css文件會(huì)導(dǎo)致壓縮不成功
            cssProcessor: require('cssnano'),
            cssProcessorOptions: { discardComments: {removeAll: true } },
            canPrint: true
        })

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

 

html-webpack-plugin 插件

 用于根據(jù)模板組合html各個(gè)部分,并插入對(duì)應(yīng)引用的js,對(duì)前后端分離貢獻(xiàn)頗多,功能強(qiáng)大會(huì)有專門的篇章來(lái)介紹

 

 browser-sync-webpack-plugin 插件

熱更新,自動(dòng)刷新瀏覽器

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

var BrowserSyncPlugin = require('browser-sync-webpack-plugin')

module.exports = {
    plugins: [        new BrowserSyncPlugin({
            host: 'localhost',
            port: 3000,
            server: { baseDir: ['./'] }
        })
    ]
}

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

 

baseDir: localhost:3000 指定的目錄

結(jié)合webpack的watch,可以做到實(shí)時(shí)編譯并刷新瀏覽器

只需要  webpack --watch  即可

 

CommonsChunkPlugin 插件

提取js的公共模塊,此插件為webpack自帶的插件

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

// 提取公共模塊new webpack.optimize.CommonsChunkPlugin({
    names:  ['vendors', 'manifest'], // 公共模塊的名稱
    //filename: 'js/[name]-[chunkhash:6].js', // 公共模塊的名稱
    chunks: 'vendors',  // chunks是需要提取的模塊
    minChunks: Infinity  //公共模塊最小被引用的次數(shù)})

平面設(shè)計(jì)培訓(xùn),網(wǎng)頁(yè)設(shè)計(jì)培訓(xùn),美工培訓(xùn),游戲開(kāi)發(fā),動(dòng)畫(huà)培訓(xùn)

通常我們的js可能會(huì)引入一些公共js文件,包括一些類庫(kù),如果都打包在一個(gè)js中,這個(gè)js會(huì)變得非常

轉(zhuǎn)載請(qǐng)注明出處 https://i.cnblogs.com/EditPosts.aspx?postid=6635504

 

http://www.cnblogs.com/saysmy/p/6635504.html