成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

一看就懂之webpack基礎(chǔ)配置

woshicixide / 1791人閱讀

摘要:一看就懂之基礎(chǔ)配置一簡(jiǎn)介本質(zhì)上,是一個(gè)現(xiàn)代應(yīng)用程序的靜態(tài)模塊打包器。屬性表示的是的上下文目錄,配置入口文件的時(shí)候,如果入口文件使用的是相對(duì)路徑,那么就是相對(duì)于所在的目錄。通常用于指定以何種方式導(dǎo)出庫(kù),通常用于指定接收庫(kù)的名稱。

一看就懂之webpack基礎(chǔ)配置 一、webpack 簡(jiǎn)介
本質(zhì)上,webpack 是一個(gè)現(xiàn)代 JavaScript 應(yīng)用程序的靜態(tài)模塊打包器(module bundler)。當(dāng) webpack 處理應(yīng)用程序時(shí),它會(huì)遞歸地構(gòu)建一個(gè)依賴關(guān)系圖(dependency graph),其中包含應(yīng)用程序需要的每個(gè)模塊,然后將所有這些模塊打包成一個(gè)或多個(gè) bundle。
簡(jiǎn)單說(shuō),webpack可以看做是一個(gè)模塊打包機(jī),主要作用就是: 分析你的項(xiàng)目結(jié)構(gòu),找到JavaScript模塊以及一些瀏覽器不能直接運(yùn)行的拓展語(yǔ)言(sass、less、typescript等),然后將它們打包為合適的格式以供瀏覽器使用。

webpack主要實(shí)現(xiàn)的功能:

代碼轉(zhuǎn)換(如: ES6轉(zhuǎn)換ES5、sass和less轉(zhuǎn)換為css等)
文件優(yōu)化(如: 將模塊內(nèi)容進(jìn)行壓縮)
代碼分割(如: 多頁(yè)面應(yīng)用公共模塊的抽離、路由懶加載)
模塊合并(如: 按照不同的功能將多個(gè)模塊合并為一個(gè)模塊)
自動(dòng)刷新(如: 啟動(dòng)本地服務(wù),代碼更新后進(jìn)行自動(dòng)刷新)
代碼校驗(yàn)(如: 添加eslint進(jìn)行代碼規(guī)范檢查)
自動(dòng)發(fā)布(如: 應(yīng)用打包完成后,自動(dòng)發(fā)布)
二、webpack 安裝

在webpack 3中,webpack本身和它的CLI以前都是在同一個(gè)包中的,但在第4版之后,已經(jīng)將兩者分開來(lái)更好地管理它們,所以安裝webpack4之后的版本,要同時(shí)安裝webpack和webpack-cli

注意,安裝webpack的時(shí)候,必須進(jìn)行本地安裝才能生效,否則會(huì)報(bào)錯(cuò),如:
但是全局安裝了也有一個(gè)好處,那就是可以在項(xiàng)目根目錄下直接執(zhí)行webpack即可完成項(xiàng)目的打包,如果沒有進(jìn)行全局安裝,那么可以通過(guò)npx直接執(zhí)行項(xiàng)目本地安裝的模塊,即 npx webpack也可以完成項(xiàng)目的打包。
三、webpack 基礎(chǔ)配置

webpack是支持零配置的,即不需要配置文件即可完成打包,其默認(rèn)入口文件為項(xiàng)目根目錄下的src目錄下的index.js文件,其默認(rèn)出口為項(xiàng)目根目錄下的dist目錄的main.js

如果沒有給webpack添加配置文件,那么webpack的打包能力就會(huì)非常弱,webpack執(zhí)行的時(shí)候默認(rèn)會(huì)加載項(xiàng)目根目錄下的webpack.config.js文件,注意,該配置文件是一個(gè)js文件,而不是json文件,并且其是通過(guò)node去執(zhí)行的,所以其完全支持node語(yǔ)法,即node中能用的,在配置文件中都可以用
webpack配置文件必須要對(duì)外暴露一個(gè)對(duì)象,即通過(guò)module.exports進(jìn)行對(duì)外暴露,其中的所有配置都必須寫在這個(gè)對(duì)外暴露的對(duì)象中。

context
context屬性表示的是webpack的上下文目錄,配置入口文件的時(shí)候,如果入口文件使用的是相對(duì)路徑,那么就是相對(duì)于context所在的目錄。

context默認(rèn)值為執(zhí)行webpack命令時(shí)所在的當(dāng)前工作目錄,通常是在項(xiàng)目根目錄下執(zhí)行webpack命令,所以可以認(rèn)為其值默認(rèn)為項(xiàng)目根目錄,所以如果入口文件路徑寫成相對(duì)路徑,最好將context配置成context: path.resolve(__dirname),以防止在非項(xiàng)目根目錄下執(zhí)行webpack命令時(shí)找不到入口文件路徑而報(bào)錯(cuò)。

entry

entry用于配置模塊的入口文件,可以配置多個(gè),webpack將從入口文件開始搜索以及遞歸解析所有入口文件依賴的模塊,其是必填的,如果配置文件中沒有entry則會(huì)報(bào)錯(cuò)。entry的屬性值可以是表示路徑的單個(gè)字符串,也可以是數(shù)組,數(shù)組中的元素為入口文件的路徑,還可以是對(duì)象,對(duì)象的屬性名為入口文件的chunk名,即打包后輸出文件的名字,屬性值為入口文件的路徑。注意,入口文件的路徑可以是絕對(duì)路徑,也可以是相對(duì)路徑,相對(duì)路徑默認(rèn)是以配置文件中的context屬性值表示的路徑
module.exports = {
    entry: "./foo.js" // 屬性值為一個(gè)表示路徑的字符串
}
其輸出結(jié)果文件取決于配置文件的output配置,如果output.filename沒有配置,則默認(rèn)輸出為main.js,如果output.filename值為指定的名稱,則輸出結(jié)果為output.filename的屬性值
module.exports = {
    entry: [ "./foo.js", "./bar.js"] // 屬性值為一個(gè)數(shù)組
}
其輸出結(jié)果文件也是取決于配置文件的output配置,只不過(guò),其會(huì)將foo.js和bar.js一起打包輸出為一個(gè)文件,如果output.filename沒有配置,則默認(rèn)輸出為main.js,如果output.filename值為指定的名稱,則輸出結(jié)果為output.filename的屬性值
module.exports = {
    entry: { // 屬性值為一個(gè)對(duì)象
        a: "./src/bar.js",
        b: "./src/foo.js",
        c: "./src/index.js"
    }
}
其輸出結(jié)果不再取決于output.filename的配置,因?yàn)閑ntry已經(jīng)指定好了模塊輸出的chunk名,即會(huì)分別輸出a.js、b.js和c.js三個(gè)文件,并且此時(shí)output.filename屬性值不能配置為一個(gè)固定名稱的輸出文件,因?yàn)?strong>入口文件有多個(gè),必然輸出文件也會(huì)有多個(gè)
chunk和module的區(qū)別,二者都是表示模塊,但是module可以看做是具有獨(dú)立功能的小模塊,即小塊,也就是打包之前,程序員編寫的一個(gè)一個(gè)的文件,每個(gè)文件稱為一個(gè)module;而chunk則可以看做是由多個(gè)小module打包成的大模塊,即大塊

output
output配置的是如何輸出最終想要的代碼,output是一個(gè)object。

path: 用于配置打包后輸出文件的本地存放目錄,必須是絕對(duì)路徑,當(dāng)然也可以不配置,因?yàn)槿绻麤]有配置path,那么會(huì)自動(dòng)在執(zhí)行webpack命令時(shí)所在的目錄下自動(dòng)創(chuàng)建dist目錄并將打包結(jié)果輸出到dist目錄下,與context的配置路徑無(wú)關(guān)

module.exports = {
    output: {
        path: path.resolve(__dirname, "./dist") // 必須是絕對(duì)路徑
    }
}

filename: 用于配置輸出文件的名稱,如果只有一個(gè)輸出文件,那么可以配置成靜態(tài)不變的文件名,如:

module.exports = {
    output: {
        filename: "bundle.js"
    }
}

但是,如果有多個(gè)chunk要輸出時(shí),即入口文件配置了多個(gè)時(shí),那么filename就不能配置成靜態(tài)不變的了,就必須借助模板和變量了,常見的兩個(gè)變量,如:
[name]: 可以自動(dòng)獲取到入口文件配置的chunk名稱;
[hash]: 可以自動(dòng)生成hash值,hash值的長(zhǎng)度是可以指定的,默認(rèn)為20位;

module.exports = {
    output: {
        filename: "[name][hash:8].js" // 以入口文件設(shè)置的chunk作為輸出名,并且指定hash值為8位
    }
}

library和libraryTarget: 用于指定將模塊的輸出結(jié)果掛載到哪個(gè)地方或者以什么樣的方式導(dǎo)出庫(kù)(模塊輸出結(jié)果)。二者通常要搭配一起使用。
libraryTarget通常用于指定以何種方式導(dǎo)出庫(kù),library通常用于指定接收庫(kù)的名稱。
我們將入口的一個(gè)或多個(gè)js文件打包輸出后的結(jié)果也是一個(gè)js文件,在沒有配置library和libraryTarget的時(shí)候,這個(gè)輸出的js文件中包含了一個(gè)匿名自執(zhí)行函數(shù), 即輸出文件的執(zhí)行結(jié)果沒有被任何東西接收,我們引入輸出文件執(zhí)行后不會(huì)得到任何結(jié)果。 如:

(function(){
    console.log("foo");
    return "foo"; // 雖然有返回值,但是匿名自執(zhí)行函數(shù)執(zhí)行完畢后拿不到任何結(jié)果
})();
// 我們以var 變量 的方式來(lái)接收函數(shù)的返回值
var foo = (function(){ // 匿名自執(zhí)行函數(shù)執(zhí)行完畢后就會(huì)將函數(shù)返回值保存到foo變量上
    console.log("foo");
    return "foo";
})();
console.log(`foo is ${foo}`);
打包后的輸出文件的輸出結(jié)果(導(dǎo)出結(jié)果),就是入口文件的輸出結(jié)果(導(dǎo)出結(jié)果),即入口文件通過(guò)export、exports、module.exports等輸出(導(dǎo)出)的結(jié)果

var: 將libraryTarget設(shè)置為var, 同時(shí)指定一個(gè)自定義的變量名來(lái)接收模塊的輸出,這個(gè)自定義的變量名就是library的屬性值

module.exports = {
    output: {
        filename: "bundle.js",
        path: path.resolve(__dirname, "./dist/"),
        libraryTarget: "var",
        library: "test"
    }
}

模塊的輸出結(jié)果將會(huì)賦值給test變量,其輸出文件bundle.js內(nèi)容大致如下:

var test = (function(modules){
    return result; // 返回值result將會(huì)被賦值給test變量 
})();

commonjs: 將libraryTarget設(shè)置為commonjs, 即通過(guò)commonjs規(guī)范導(dǎo)出,同時(shí)指定一個(gè)自定義的變量名來(lái)接收模塊的輸出,這個(gè)自定義的變量名就是library的屬性值, 只不過(guò)這個(gè)自定義的變量名是exports的屬性名,如:

module.exports = {
    output: {
        filename: "bundle.js",
        path: path.resolve(__dirname, "./dist/"),
        libraryTarget: "commonjs",
        library: "test"
    }
}

模塊的輸出結(jié)果將會(huì)賦值給exports["test"]上,其輸出文件bundle.js內(nèi)容大致如下:

exports["test"] = (function(modules){
    return result; // 返回值result將會(huì)被賦值給exports["test"]
})();

commonjs2: 將libraryTarget設(shè)置為commonjs2,即通過(guò)commonjs2規(guī)范導(dǎo)出,此時(shí)library的配置將無(wú)意義,因?yàn)閏ommonjs2的輸出是固定的module.exports,所以不需要指定library了,如:

module.exports = {
    output: {
        filename: "bundle.js",
        path: path.resolve(__dirname, "./dist/"),
        libraryTarget: "commonjs2"
    }
}

模塊的輸出結(jié)果將會(huì)被賦值到module.exports上,其輸出文件bundle.js內(nèi)容大致如下:

module.exports = (function(modules){
    return result; // 返回值result將會(huì)被賦值給module.exports
})();
commonjs和commonjs2的區(qū)別在于,commonjs只能使用exports進(jìn)行導(dǎo)出,而commonjs2在commonjs的基礎(chǔ)上增加了module.exports進(jìn)行導(dǎo)出;

this: 將libraryTarget設(shè)置為this, 那么此時(shí)library配置的變量名將作為this的屬性名來(lái)接收模塊的導(dǎo)出結(jié)果,如:

module.exports = {
    output: {
        filename: "bundle.js",
        path: path.resolve(__dirname, "./dist/"),
        libraryTarget: "this",
        library: "test"
    }
}

模塊的輸出結(jié)果將會(huì)被賦值到this["test"] 上,其輸出文件bundle.js內(nèi)容大致如下:

this["test"] = (function(modules){
    return result; // 返回值result將會(huì)被賦值給this["test"]
})();

同理libraryTarget的屬性值還可以是window、global,這里就不一一列舉了。

publicPath
publicPath用于配置打包資源發(fā)布到線上時(shí)服務(wù)器的url地址,打包完成后,html文件中如果引入了js、image、css等資源,那么都會(huì)在前面加上publicPath所表示的路徑

module.exports = {
    output: {
        filename: "bundle.js",
        path: path.resolve(__dirname, "./dist/"),
        publicPath: "http://www.lihb.com/"
    }
}

// index.html




    
四、webpack 打包輸出后的內(nèi)容分析

webpack打包輸出后的結(jié)果默認(rèn)是一個(gè)匿名自執(zhí)行函數(shù),匿名自執(zhí)行函數(shù)傳遞的參數(shù)為一個(gè)對(duì)象,對(duì)象的屬性名為入口文件的路徑名,屬性值為一個(gè)函數(shù),函數(shù)體內(nèi)部通過(guò)會(huì)執(zhí)行eval(),eval()方法的參數(shù)為入口文件的內(nèi)容字符串,而這個(gè)匿名自執(zhí)行函數(shù),內(nèi)部有一個(gè)自定義的__webpack_require__方法,該方法需要傳入入口文件的路徑名作為參數(shù),匿名自執(zhí)行函數(shù)執(zhí)行完成后會(huì)返回__webpack_require__的結(jié)果,而__webpack_require__()方法內(nèi)部執(zhí)行的時(shí)候,會(huì)首先創(chuàng)建一個(gè)module對(duì)象module對(duì)象里面有exports屬性,屬性值為一個(gè)空的對(duì)象,用于接收入口文件的模塊輸出,如:

(function(modules) {
    function __webpack_require__(moduleId) { // 傳入入口文件的路徑
        var module = installedModules[moduleId] = { // 創(chuàng)建一個(gè)module對(duì)象
             i: moduleId,
             l: false,
             exports: {} // exports對(duì)象用于保存入口文件的導(dǎo)出結(jié)果
         };
        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); // 執(zhí)行入口文件
        return module.exports; // 返回模塊輸出結(jié)果
    }
    return __webpack_require__(__webpack_require__.s = "./src/bar.js"); // 返回入口文件
})({
     "./src/bar.js": (function(module, exports) {
         eval("module.exports = "bar";");
     })
  });
所以不管入口文件是以ES6模塊的方式輸出還是以commonjs模塊的方式輸出,最終入口文件的模塊輸出結(jié)果都會(huì)被綁定到__webpack_require__方法中定義的module對(duì)象的exports屬性上,只不過(guò),如果是以commonjs的方式輸出,那么入口文件的輸出結(jié)果將會(huì)直接替換掉__webpack_require__方法中定義的module對(duì)象的exports屬性;如果是以ES6模塊的方式輸出,則是在__webpack_require__方法中定義的module對(duì)象的exports屬性值中添加一個(gè)default屬性或者具體變量名來(lái)保存入口文件的輸出。
五、webpack 本地服務(wù)器配置

為了更方便調(diào)試,我們需要用到webpack的本地http服務(wù)器功能,要想使用webpack提供的Web服務(wù)器功能,我們需要安裝webpack-dev-server模塊,webpack-dev-server會(huì)啟動(dòng)一個(gè)web服務(wù)器用于實(shí)現(xiàn)網(wǎng)頁(yè)請(qǐng)求,也可以監(jiān)聽文件的變化自動(dòng)刷新網(wǎng)頁(yè)。

webpack-dev-server模塊安裝完成后,我們可以在項(xiàng)目根目錄下運(yùn)行npx webpack-dev-server,其和webpack命令一樣,如果沒有配置文件,則使用內(nèi)置默認(rèn)配置進(jìn)行打包輸出,如果有則使用配置文件中的配置,只不過(guò)其不會(huì)將打包結(jié)果輸出到指定的目錄中,因?yàn)閣ebpack-dev-server會(huì)忽略配置文件中的output.path配置,其會(huì)將打包輸出結(jié)果保存到內(nèi)存中。webpack-dev-server啟動(dòng)后會(huì)默認(rèn)將啟動(dòng)devServer時(shí)所在的目錄作為根目錄,即執(zhí)行npx webpack-dev-server命令時(shí)所在的目錄。

webpack提供了一個(gè)devServer屬性用于配置啟動(dòng)的服務(wù)器的一些參數(shù),當(dāng)然webpack本身是無(wú)法識(shí)別devServer屬性配置的,只有通過(guò)webpack-dev-server去啟動(dòng)webpack時(shí),devServer的配置才會(huì)生效。

module.exports = {
    devServer: {
        port: 3000, // 讓devServer監(jiān)聽3000端口
        contentBase: "./dist", // 將當(dāng)前項(xiàng)目的dist目錄作為devServer的根目錄
        progress: true, // 顯示打包進(jìn)度條
        compress: true // 是否啟用Gzip壓縮,默認(rèn)為false
    }
}
webpackDevServer啟動(dòng)后,默認(rèn)會(huì)自動(dòng)監(jiān)聽打包源文件的變化,如果修改了打包源文件,那么會(huì)自動(dòng)重新打包到內(nèi)存,并且會(huì)自動(dòng)刷新瀏覽器,但是自動(dòng)刷新瀏覽器功能必須將target設(shè)置成web,否則自動(dòng)刷新功能將會(huì)失效,比如target為node就無(wú)法起作用。
六、webpack 插件配置

在不使用插件的時(shí)候,webpack默認(rèn)只能打包輸出js文件,如果我們想要輸出其他格式的文件到輸出目錄中,那么我們必須使用插件。webpack提供了一個(gè)plugins屬性用于配置使用到的插件,其屬性值為一個(gè)數(shù)組,數(shù)組中的元素為插件對(duì)象,通常插件都是一個(gè)類,我們需要通過(guò)插件類來(lái)創(chuàng)建一個(gè)插件對(duì)象。
html-webpack-plugin
該插件可以指定一個(gè)html文件,webpack會(huì)將該html文件打包輸出到輸出目錄中,同時(shí)會(huì)將打包輸出后的文件自動(dòng)插入到該html文件中,即讓該html文件自動(dòng)引入打包后的js文件。

module.exports = {
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html", // 要打包輸出哪個(gè)文件,可以使用相對(duì)路徑
            filename: "index.html", // 打包輸出后該html文件的名稱
            minify: {
                removeAttributeQuotes: true, // 去除html文件中的引號(hào)
                collapseWhitespace: true // 合并空格,即將html進(jìn)行單行顯示
            },
            hash: true // 向html文件中引入打包后的js時(shí)候帶上hash值
        })
    ]
}
html插件中配置了hash為true, 是在引入打包后的js的時(shí)候帶上hash值,如:
七、webpack 模塊配置

webpack默認(rèn)將所有格式的文件都當(dāng)做模塊進(jìn)行處理,但是wepback默認(rèn)只能處理js模塊。如果在js中通過(guò)require引入了其他格式的模塊(文件),那么webpack就必須通過(guò)安裝合適的模塊加載器,才能正確解析對(duì)應(yīng)的模塊內(nèi)容,webpack提供了一個(gè)module屬性,用于進(jìn)行模塊解析器的配置,其屬性值為一個(gè)對(duì)象,對(duì)象中有一個(gè)rules屬性,其屬性值為一個(gè)數(shù)組,數(shù)組中的元素為一個(gè)對(duì)象,該對(duì)象主要完成兩件事,匹配對(duì)應(yīng)格式的文件,并且使用對(duì)應(yīng)模塊加載器進(jìn)行加載,匹配使用的是test屬性,屬性值為一個(gè)正則表達(dá)式,【使用】使用的是use屬性,屬性值可以是字符串也可以是數(shù)組,如果只有一個(gè)模塊加載器的時(shí)候,可以使用字符串的形式,如果有多個(gè)模塊加載器的時(shí)候,那么就需要使用數(shù)組的形式,當(dāng)然,如果模塊加載器需要傳遞參數(shù)配置,那么可以將模塊加載器寫成對(duì)象的形式,通過(guò)loader屬性指定模塊加載器名稱,通過(guò)options屬性傳遞參數(shù)配置。

① 處理css樣式,需要使用到css-loader和style-loader。
首先需要安裝css-loader和style-loader。
css-loader必須同時(shí)和style-loader一起使用才能正確加載css文件,一個(gè)負(fù)責(zé)加載,一個(gè)負(fù)責(zé)插入。css-loader負(fù)責(zé)加載css, 即在js文件中能夠通過(guò)require的方式引入css,即加載和解析css,同時(shí)支持在css文件中使用@ import的方式引入其他css文件,style-loader負(fù)責(zé)將加載并解析好的css文件插入到html文件中去,從名字可以看出其是在html文件中生成style標(biāo)簽來(lái)引入css文件,loader的執(zhí)行順序是從右向左,所以必須先加載然后再插入

比如,打包入口文件index.js中通過(guò)require的方式引入了一個(gè)index.js文件,即require("./index.css"),那么webpack需要進(jìn)行如下配置:

module.exports = {
    module: {
        rules: [
            {
                test: /.css$/, // 匹配以.css結(jié)尾的文件
                use: [ // 并交給css-loader和style-loader進(jìn)行處理
                    {
                        loader: "style-loader", // 以對(duì)象的形式配置loader
                        options: { // 通過(guò)options給loader傳遞參數(shù)
                            insertAt: "top" // 默認(rèn)為bottom, 將加載的css文件插入到head標(biāo)簽的最上面,即優(yōu)先級(jí)最低,會(huì)被覆蓋
                        }
                    },
                    "css-loader" // 直接以字符串的形式配置loader
                ]
            }
        ]
    }
}
打包輸出后,會(huì)將index.css中的內(nèi)容放到