Webpack 工程化基礎(chǔ)

webpack 基礎(chǔ)

Wepack 工程打包機(jī)
Webpack 基本概念
Webpack Demos
Node.js Debugger
webpack學(xué)習(xí)實(shí)踐系列
Webpack Dev Server
Webpack loader 十問

Webpack 總得來說是一個(gè)資源模塊化 JS Module 打包工具拷泽,它的核心思想是模塊化思想,不管你是圖片嬉愧,JS挣柬,CSS,SCSS耻台,LESS凶杖,還是 JSX使碾,統(tǒng)統(tǒng)都打包成 JS Module种远,Anythin to JS Modules涩澡。各種資源都有相適配的加載器 Loaders 負(fù)責(zé)對(duì)資源進(jìn)行處理,Webpack 通過執(zhí)行加載器完成原始資源的轉(zhuǎn)換坠敷。

Hello Webpack

TypeScript
TypeScript Samples
TypeScript Node Starte
TS-Node
Webpack with TypeScript
Awesome TypeScript Loader
TypeScript loader for webpack
Babel loader for webpack
Base64 URL Loader
Webpack 資源管理
TypeScript聲明文件 .d.ts
Build Performance

這里同過 TypeScript + Webpack 編寫一個(gè) Demo 工程來入門 Webpack 工程化打包機(jī)的理念妙同,工程化是必然的軟件技術(shù)發(fā)展方向射富。TypeScript 作為一個(gè)強(qiáng)大的靜態(tài)類型檢查語(yǔ)言是作為工程化開發(fā)的理想工具,所以 Node.js + TypeScript + Webpack + 框架的工程結(jié)構(gòu)將會(huì)是非常流行的技術(shù)棧渐溶。TypeScript 現(xiàn)在發(fā)布 v3.5.3 版本辉浦,官方提供的示例 [TypeScript Node Starte] 是非常值得學(xué)習(xí)的案例。

Node.js 命令行的 TypeScript 編譯器可以使用 npm 來安裝茎辐,安裝后會(huì)有一個(gè) tsc 命令來轉(zhuǎn)譯 TypeScript 代碼為 JavaScript,也可以安裝 ts-node 來直接解析運(yùn)行掂恕。

npm install --save-dev typescript@3.5.3 ts-node@8.3.0
tsc helloworld.ts
ts-node helloworld.ts

使用 VSCode拖陆、Sublime Text、Vim 作為開發(fā)工具都是很好的選擇懊亡。

通過 Node.js 環(huán)境使用 Webpack依啰,先通過 npm 來進(jìn)行全局安裝,創(chuàng)建示例工程 webpack-demo 目錄店枣,npm init 項(xiàng)目初始化命令生成默認(rèn)的 package.json 配置文件速警,可以傳入默許參數(shù) --yes 忽略設(shè)置內(nèi)容,關(guān)于它得用法可以查詢 npm help init鸯两。一并安裝 webpack-dev-server 這個(gè)開發(fā)用的 Web 服務(wù)器闷旧,還有 TypeScript 支持。

Webpack 處理 TypeScript (.ts) 原代碼文件需要用到 ts-loaderawesome-typescript-loader钧唐,前者使用得更多忙灼。在代碼中導(dǎo)入文件資源時(shí)需要 file-loader,導(dǎo)入圖片時(shí)需要 url-loader钝侠,它可以對(duì)常用得圖片進(jìn)行 Base64編碼该园,可以設(shè)置 limit 選項(xiàng)來限定待編碼文件大小。在處理 CSS 樣式文件時(shí)會(huì)用到 css-loader帅韧,打包后的樣式在頁(yè)面上還原出來時(shí)需要style-loader 提供的功能里初,它會(huì)在 <head> 節(jié)點(diǎn)下插入一個(gè) <style> 節(jié)點(diǎn),通過寫入樣式規(guī)則來還原經(jīng)過打包的樣式忽舟。

由于 TypeScript 靜態(tài)類型的特殊性双妨,那些非代碼資源需要為 TypeScript 提供一個(gè) Type Declaration 類型聲明文件 .d.ts,在工程原代碼目錄下保存即可萧诫,TypeScript 會(huì)自動(dòng)解析斥难。如編寫一個(gè) .svg 資源的D類型聲明文件:

// custom.d.ts
declare module "*.svg" {
  const content: any;
  export default content;
}

這個(gè) SVG 類型聲明模塊指明,任何以 .svg 結(jié)尾的文件導(dǎo)入時(shí)將擁有一個(gè) any 任意類型屬性的 content帘饶,即數(shù)據(jù)部分是任意類型哑诊。還可以顯式定義 url 屬性為 string,即文件的地址及刻。 這個(gè)De類型聲明規(guī)則同樣適用于 CSS, SCSS, JSON 等等镀裤,這是 TypeScript 靜態(tài)類型系統(tǒng)特有的做法竞阐。

TypeScript 相比 JavaScript 增加了類型聲明。這些類型聲明幫助編譯器識(shí)別類型暑劝,從而防止開發(fā)者搬起石頭砸自己的腳骆莹。

原則上,TypeScript 需要開發(fā)者做到先聲明后使用担猛。這就導(dǎo)致開發(fā)者在調(diào)用很多原生接口(瀏覽器幕垦、Node.js)或者第三方模塊的時(shí)候,因?yàn)槟承┤肿兞炕蛘邔?duì)象的方法并沒有聲明過傅联,導(dǎo)致編譯器的類型檢查失敗先改。

用 ts 寫的模塊在發(fā)布的時(shí)候仍然是用 js 發(fā)布,這就導(dǎo)致一個(gè)問題:ts 那么多類型數(shù)據(jù)都沒了蒸走,所以需要一個(gè) d.ts 文件來標(biāo)記某個(gè) js 庫(kù)里面對(duì)象的類型
然后 typings 就是一個(gè)網(wǎng)絡(luò)上的 .d.ts 數(shù)據(jù)庫(kù)仇奶。

Lodash 是一個(gè)一致性、模塊化比驻、高性能的 JavaScript 實(shí)用工具庫(kù)该溯。它通過降低 array、number别惦、objects狈茉、string 等等的使用難度從而讓 JavaScript 變得更簡(jiǎn)單的工具類。Lodash 的模塊化方法 非常適用于做 array步咪、object 和 string 的遍歷操作论皆,對(duì)值進(jìn)行操作和檢測(cè),創(chuàng)建符合功能的函數(shù)等猾漫。

source-map-loader 是一個(gè) SourceMap 代碼地圖工具点晴,可以生成代碼地圖方便做調(diào)式。配置時(shí)可以在配置 devtool 設(shè)置內(nèi)聯(lián) inline-source-mapsource-map 方式悯周,前者會(huì)將調(diào)式代碼嵌入打包輸出粒督,后者則獨(dú)立保存為 .map 代碼地圖文件。

mkdir webpack-demo
cd webpack-demo
npm init --yes
npm install --save-dev webpack@4.1.1 webpack-cli@3.3.6 webpack-dev-server@3.7.2
npm install --save-dev file-loader@4.0.0 url-loader@2.0.1 ts-loader@6.0.4 css-loader@3.0.0 style-loader@0.23.1
npm install --save-dev awesome-typescript-loader@5.2.1
npm install --save-dev lodash@4.17.14 source-map-loader@0.2.4

配置文件參考禽翼,main 這里設(shè)置的式項(xiàng)目入口程序屠橄,如果已經(jīng)準(zhǔn)備好配置文件,直接執(zhí)行 npm install 就可以根據(jù)配置好的依賴模塊列表進(jìn)行下載安裝:

{
  "name": "webpack",
  "version": "1.0.0",
  "description": "Webpack Getting Started",
  "main": "index.ts",
  "devDependencies": {
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^3.0.0",
    "file-loader": "^4.0.0",
    "html-webpack-plugin": "^3.2.0",
    "html-webpack-template": "^6.2.0",
    "lodash": "^4.17.14",
    "source-map-loader": "^0.2.4",
    "style-loader": "^0.23.1",
    "ts-loader": "^6.0.4",
    "ts-node": "^8.3.0",
    "typescript": "^3.5.3",
    "url-loader": "^2.0.1",
    "webpack": "^4.1.1",
    "webpack-cli": "^3.3.6",
    "webpack-dev-server": "^3.7.2"
  },
  "dependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server --devtool eval --progress --colors",
    "build": "set NODE_ENV=production&& webpack -p"
  },
  "author": "Jeango",
  "license": "ISC"
}

需要注意的式闰挡,加載的模塊愈多锐墙,就越消耗硬件資源,因此沒有必要使用的組件就不要安裝了长酗,直接從配置文件中移除然后從新執(zhí)行 npm install 安裝即可更新配置溪北。
例如給給規(guī)則指定 include 目錄節(jié)省搜索時(shí)間,簡(jiǎn)化 resolve.modules, resolve.extensions, resolve.mainFiles, resolve.descriptionFiles。使用 DllPlugin 插件將那些不怎么修改的內(nèi)容分離到另一個(gè)編譯單元之拨,避免在開發(fā)過程使用 source-mapminimize茉继,特別是代碼地圖 Source maps 它非常耗資源,請(qǐng)考慮是否真的需要蚀乔。

可以使用并行編譯烁竭,parallel-webpackcache-loader 提供并行編譯的能力,后者對(duì)性能開銷較大的 loader 提供緩存服務(wù)吉挣。具體要點(diǎn)參考官方的構(gòu)建優(yōu)化文檔[Build Performance]派撕。

rules: [
  {
    test: /\.js$/,
    include: path.resolve(__dirname, 'src'),
    loader: 'babel-loader'
  }
]

webpack 命令的基本用法

webpack             – building for development
webpack -p          – building for production (minification)
webpack --watch     – for continuous incremental building
webpack -d          – including source maps
webpack --colors    – making building output pretty

為了方便使用打包命令,可以配置到 package.json 中的 scripts听想,例如要運(yùn)行開發(fā)服務(wù)器 webpack-dev-server 只需要執(zhí)行 npm run dev腥刹,要生成發(fā)布打包就執(zhí)行 npm run build,另外 VSCode 對(duì)這里設(shè)置的命令配置項(xiàng)支持很到位汉买,直接通過 VSCode 的 Terminal 菜單 Run Task 就可以執(zhí)行。Sublime

{
  "scripts": {
    "dev": "webpack-dev-server --devtool eval --progress --colors",
    "build": "NODE_ENV=production webpack -p"
  },
}

接下來需要一個(gè) TypeScript 配置文件 tsconfig.json佩脊,因?yàn)?TypeScript 需要使用到 Node.js 的類型信息蛙粘,模塊解析moduleResolution 設(shè)置成 node 模式。其它配置項(xiàng)信息可以參考官方文檔 [TypeScript]威彰。

{
    "compilerOptions": {
        "outDir": "./dist/", // path to output directory
        "sourceMap": true, // allow sourcemap support
        "strictNullChecks": true, // enable strict null checks as a best practice
        "module": "es6", // specifiy module code generation
        "target": "es5", // specify ECMAScript target version
        "allowJs": true, // allow a partial TypeScript and JavaScript codebase  
        "moduleResolution": "node",
        "noImplicitAny": true, // disallow implicit any type
        "noImplicitReturns": true,
        "strict": true,
    },
    "include": ["./src/"]
}

安裝各種 Loaders 后出牧,需要根據(jù) Loader 開發(fā)文檔參考配置,Webpack 得配置文件是 webpack.config.js 官方文檔有很詳細(xì)得說明歇盼。對(duì)于 Loader舔痕,主要是配置 rules 規(guī)則,test 是文件名匹配正則規(guī)則豹缀,符合匹配條件得文件就交給指定的 loader 進(jìn)行處理伯复,各個(gè) Loader 的配置選項(xiàng)參考文檔設(shè)置。

其中 entryoutput 是比較重要的配置邢笙,entry 表示程序入口啸如,output 表示打包出口,即打包生成的文件氮惯。publicPath 是訪問資源時(shí)使用的參考路徑叮雳,打包后的資源存放路徑與它直接關(guān)聯(lián)。在使用開發(fā)服務(wù)器時(shí)妇汗,它就是項(xiàng)目的根目錄下的路徑帘不,使用相對(duì)目錄時(shí)要參考根目錄來設(shè)置。output 還可以設(shè)置 path 屬性來指定打包文件存放位置杨箭,默認(rèn)是 dist 目錄寞焙。結(jié)合 filename 指定輸出文件就是 /dist/bin/bundle.js。如果對(duì)資源文件的發(fā)布目錄有自定義需求,可以通過 process.env.NODE_ENV 變量判端是否是發(fā)布編譯棺弊,然后再指定一個(gè) publicPath 目錄晶密。

在 Webpack 4 中,不再?gòu)?qiáng)制要求指定 entry 和 output 路徑模她。webpack 4 會(huì)默認(rèn) entry 為 ./src稻艰,output 為 ./dist

mode 模式設(shè)置侈净,基本上有 development, production, none 幾種模式尊勿。根據(jù)不同的模式使用不同的配置文件來優(yōu)化開發(fā)/發(fā)布。

resolve 設(shè)定要解析的文件類型畜侦,設(shè)置錯(cuò)誤解析不到的文件類型會(huì)產(chǎn)生 Module not found: Error: Can't resolve...

module.exports = {
    // change to .tsx if necessary
    entry: './src/index.ts',
    mode: 'development',
    output: {
        publicPath: "/",
        filename: './bin/bundle.js'
    },
    resolve: {
        extensions: [".ts", ".tsx", ".js", ".jsx"]
    },
    module: {
        rules: [{
            test: /\.(t|j)sx?$/,
            use: {
                loader: 'ts-loader'
            }
        }, {
            test: /\.(png|jpg|gif)$/i,
            use: [{
                loader: 'url-loader',
                options: {
                    limit: 8192,
                },
            }, ],
        }, {
            test: /\.css$/i,
            use: [{
                loader: "style-loader"
            }, {
                loader: 'css-loader',
                options: {
                    modules: true,
                }
            }]
        }]
    // },
    // devtool: 'inline-source-map',
    // devtool: "source-map",
    // optimization: {
    //     minimize: true
    // },
    // externals: {
    //     "react": "React",
    //     "react-dom": "ReactDOM",
    }
}
if (process.env.NODE_ENV === "production") {
    module.exports.output.publicPath = "./release";
}

如果工程有多個(gè)主程序入口文件元扔,那么可以將 entryoutput 修改成分組打包方式。Webpack 的輸出參數(shù) output 指定規(guī)則生成輸出文件旋膳。所有的入口產(chǎn)生的輸出文件都必須使用這一套規(guī)則澎语,不能針對(duì)某一個(gè)特定的入口來制定 output 規(guī)則。輸出項(xiàng)中用 [name] 來引用 entry每一項(xiàng)中的鍵值验懊,用以批量指定生成后文件的名稱擅羞。[hash] 引用本次編譯的一個(gè)hash版本號(hào),[chunkhash] 引用的是當(dāng)前chunk的一個(gè)hash版本义图。也就是說减俏,在同一次編譯中,每一個(gè)chunk的hash都是不一樣的碱工;而在兩次編譯中娃承,如果某個(gè)chunk根本沒有發(fā)生變化,那么該chunk的hash也就不會(huì)發(fā)生變化怕篷。

html-webpack-pluginhtml-webpack-template 是兩個(gè)生成 HTML 模板的插件历筝,為了對(duì)發(fā)布目錄 dist 自動(dòng)清理,可以使用 clean-webpack-plugin 插件匙头。這幾個(gè)插件都是 Webpack 提供學(xué)習(xí)如何在 Node.js 平臺(tái)下做 Webpack 插件開發(fā)用的漫谷,也具有一定的實(shí)用。

Node.js 提供的內(nèi)置模塊 path 可以用來解析絕對(duì)路徑蹂析。

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  entry: {
    app: './src/index.js',
    print: './src/print.js'
  },
  // entry: {
  //   home: ['./home.js', './home.scss'],
  //   account: ['./account.js', './account.scss']
  // },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      title: 'Output Management'
    })
  ]
};

先準(zhǔn)備一個(gè)頁(yè)面模板 index.html 用它來加載 Webpack 打包生成的輸出文件 bundle.js舔示,為了簡(jiǎn)化這里就不引用第三方 JavaScript 庫(kù):

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>TypeScript with Webpack</title>
        <style>
            .frame {
                width:50%;
                padding:10%;
                color:white;
                background: #282828;
            }
        </style>
    </head>
    <body>
        <div id="content" class="frame"></div>
        <script src="./bin/bundle.js"></script>
    </body>
</html>

新建 src 目錄用來放源代碼 index.ts

class Student {
    fullName: string = "";
    readonly age:number = 18;
    constructor( public firstName:string, public middle:string, public lastName:string){
        this.fullName = firstName + ' ' + middle + ' ' + lastName;
    }
}

interface Person {
    firstName: string;
    lastName: string;
}

function greeter(person: Person) {
    return "Hello, " + person.firstName;
}

let user = { firstName: "Jane", lastName: "User" };
// let user = new Student("Jane", "M.", "User");

let $ = (id:string, msg:string) => {
    let tag = document.getElementById(id);
    if (!tag){
        document.body.innerHTML = ("HTML element not found #"+id);
    }else{
        tag.innerHTML = msg;
    }
}
$("content", greeter(user));

其它不需要打包的資源文件單獨(dú)放放到 public 子目錄下,這樣的工程目錄結(jié)構(gòu)是比較通用合理的电抚。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末惕稻,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蝙叛,更是在濱河造成了極大的恐慌俺祠,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蜘渣,居然都是意外死亡淌铐,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門蔫缸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來腿准,“玉大人,你說我怎么就攤上這事拾碌⊥麓校” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵校翔,是天一觀的道長(zhǎng)弟跑。 經(jīng)常有香客問我,道長(zhǎng)防症,這世上最難降的妖魔是什么孟辑? 我笑而不...
    開封第一講書人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮蔫敲,結(jié)果婚禮上扑浸,老公的妹妹穿的比我還像新娘。我一直安慰自己燕偶,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開白布础嫡。 她就那樣靜靜地躺著指么,像睡著了一般。 火紅的嫁衣襯著肌膚如雪榴鼎。 梳的紋絲不亂的頭發(fā)上伯诬,一...
    開封第一講書人閱讀 49,760評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音巫财,去河邊找鬼盗似。 笑死,一個(gè)胖子當(dāng)著我的面吹牛平项,可吹牛的內(nèi)容都是我干的赫舒。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼闽瓢,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼接癌!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起扣讼,我...
    開封第一講書人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤缺猛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體荔燎,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年有咨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了琐簇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡摔吏,死狀恐怖鸽嫂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情征讲,我是刑警寧澤据某,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站诗箍,受9級(jí)特大地震影響癣籽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜滤祖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一筷狼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧匠童,春花似錦埂材、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至扬绪,卻和暖如春竖独,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背挤牛。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工莹痢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人墓赴。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓竞膳,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親竣蹦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子顶猜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • webpack使用學(xué)習(xí) 本分享學(xué)習(xí)借鑒webpack中文官網(wǎng),官網(wǎng)鏈接(中文文檔):https://www.web...
    腿毛怪丶叔叔閱讀 870評(píng)論 0 5
  • webpack 是什么痘括? 本質(zhì)上长窄,webpack 是一個(gè)現(xiàn)代 JavaScript 應(yīng)用程序的靜態(tài)模塊打包器(mo...
    IT老馬閱讀 3,308評(píng)論 2 27
  • 一滔吠、概念 本質(zhì)上,webpack 是一個(gè)現(xiàn)代 JavaScript 應(yīng)用程序的靜態(tài)模塊打包器(module bun...
    Timmy小石匠閱讀 1,908評(píng)論 0 29
  • 全局安裝webpack 全局安裝webpack會(huì)有個(gè)問題挠日,就是當(dāng)你有兩個(gè)項(xiàng)目依賴于不同版本的webpack疮绷,就會(huì)有...
    説好的妹紙呢閱讀 1,807評(píng)論 0 11
  • 當(dāng)生活被時(shí)間打碎 開始無止境的忙碌起來 再也沒有空閑遐想 再也沒有功夫小憩 我們開始遺忘 開始迷失 停下來 靜坐一...
    花開云想閱讀 437評(píng)論 0 1