webpack中的module、chunk和bundle的區別:css
module、chunk 和 bundle 其實就是同一份邏輯代碼在不一樣轉換場景下的取了三個名字,咱們直接寫出來的是 module,webpack 處理時是 chunk,最後生成瀏覽器能夠直接運行的 bundle。html
通常來講一個 chunk 對應一個 bundle,好比上圖中的 utils.js -> chunks 1 -> utils.bundle.js
;但咱們也能夠用一些插件進行文件分離,好比說上圖中,就用 MiniCssExtractPlugin
插件從 chunks 0 中抽離出了 index.bundle.css
文件。vue
參考:https://www.cnblogs.com/skychx/p/webpack-module-chunk-bundle.htmlnode
在使用 webpack 構建的典型應用程序或站點中,有三種主要的代碼類型:react
runtime 以及伴隨的 manifest 數據,主要是指:在瀏覽器運行過程當中,webpack 用來鏈接模塊化應用程序所需的全部代碼。它包含:在模塊交互時,鏈接模塊所需的加載和解析邏輯。包括:已經加載到瀏覽器中的鏈接模塊邏輯,以及還沒有加載模塊的延遲加載邏輯。webpack
webpack 和 webpack 插件是如何「知道」應該哪些文件生成的呢?答案是,webpack 經過 manifest,能夠追蹤全部模塊到輸出 bundle 之間的映射。在你的應用程序中,形如 index.html
文件、一些 bundle 和各類資源,都必須以某種方式加載和連接到應用程序,一旦被加載到瀏覽器中。在通過打包、壓縮、爲延遲加載而拆分爲細小的 chunk 這些 webpack 優化
以後,你精心安排的 /src
目錄的文件結構都已經再也不存在。因此 webpack 如何管理全部所需模塊之間的交互呢?這就是 manifest 數據用途的由來。git
當 compiler 開始執行、解析和映射應用程序時,它會保留全部模塊的詳細要點。這個數據集合稱爲 "manifest",當完成打包併發送到瀏覽器時,runtime 會經過 manifest 來解析和加載模塊。不管你選擇哪一種 模塊語法,那些 import
或 require
語句如今都已經轉換爲 __webpack_require__
方法,此方法指向模塊標識符(module identifier)。經過使用 manifest 中的數據,runtime 將可以檢索這些標識符,找出每一個標識符背後對應的模塊。es6
經過使用內容散列(content hash)做爲 bundle 文件的名稱,這樣在文件內容修改時,會計算出新的 hash,瀏覽器會使用新的名稱加載文件,從而使緩存無效。一旦你開始這樣作,你會當即注意到一些有趣的行爲。即便某些內容明顯沒有修改,某些 hash 仍是會改變。這是由於,注入的 runtime 和 manifest 在每次構建後都會發生變化。github
Babel實際上是一個編譯JavaScript的平臺,它能夠編譯代碼幫你達到如下目的:web
Babel實際上是幾個模塊化的包,其核心功能位於稱爲babel-core
的npm包中,webpack能夠把其不一樣的包整合在一塊兒使用,對於每個你須要的功能或拓展,你都須要安裝單獨的包.
用得最多的是解析Es6的babel-preset-
包和解析JSX的babel-preset-react
包。
下面測試使用 babel 來解析支持 es6 和 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/ } ] } };
配置完以上選項後就能支持ES6以及JSX的語法了。測試:
npm install --save react react-dom
//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
import React from 'react';
import {render} from 'react-dom'; import Greeter from './Greeter'; render(<Greeter />, document.getElementById('root'));
直接編譯或者在本地服務器上就能看到運行結果
Babel其實能夠徹底在 webpack.config.js
中進行配置,可是考慮到babel具備很是多的配置選項,在單一的webpack.config.js
文件中進行配置每每使得這個文件顯得太複雜,所以一些開發者支持把babel的配置選項放在一個單獨的名爲 ".babelrc" 的配置文件中。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"] }
因爲以前的一些編譯可能會致使用於輸出的文件夾中包含了一些不必的文件,顯得比較雜亂,咱們能夠用clean-webpack-plugin
插件清理輸出的文件夾中的文件。
該插件會在每次構建前清理輸出文件夾,只會生成用到的文件。
npm install clean-webpack-plugin --save-dev
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin'); module.exports = { entry: { app: './src/index.js', print: './src/print.js' }, plugins: [ new CleanWebpackPlugin(['public/*.*'], { root: __dirname, verbose: true, //開啓在控制檯輸出信息 dry: false }) ], output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist') } };
有一個問題是當熱加載和CleanWebpackPlugin插件同時使用時,運行dev-sever會從新編譯,由此也從新使用清理插件,目標文件夾中的文件將被所有刪除,可是此時並不生成新的文件。
雖然沒報什麼問題,代碼也能夠跑,可是仍是困惑了我好久。這個問題應該是運行webpack-dev-server時webpack會從新編譯,由此使用了清理插件,可是dev-server並不會在工做目錄中生成編譯的文件,而是在內存中生成,因此看不到,可是代碼跑的沒問題。
要想解決這個問題,我在GitHub上看到了一個issue,可是嘗試了好像會報錯:https://github.com/johnagan/clean-webpack-plugin/issues/96。事後會繼續關注該問題。
這些選項能設置模塊如何被解析。
在咱們引入一些模塊文件時,可能文件路徑層次比較深,這樣的話就會致使相對路徑的寫法比較長。經過 resolve.alias 可以將一些路徑配置成指定的別名,可以讓咱們簡寫路徑。
module.exports = { ... resolve: { alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), //由此引入src文件夾下的文件就能夠寫成:import xxx from @/xxx.js } }, }
經過指定 resolve 字段的extensions值能夠指定自動解析的文件擴展名。
webpack的默認配置爲:
module.exports = { //... resolve: { extensions: ['.wasm', '.mjs', '.js', '.json'] } };
由此用戶在引入模塊一些文件時就能夠不帶擴展,好比:
//引入 mian.js import aaa from '../path/to/main';
若是咱們自定義該選項,就會覆蓋默認數組即webpack的默認配置,這就意味着 webpack 將再也不嘗試使用默認擴展來解析模塊,對於須要指定自動解析的文件擴展名必須得寫入該數組中。
告訴 webpack 解析模塊時應該去哪一個目錄搜索該模塊。
webpack的默認配置爲:
module.exports = { //... resolve: { modules: ['node_modules'] } };
webpack-dev-server 可以用於快速開發應用程序。