Webpack 原理與實踐之如何通過 Loader 加載器進行資源加載?
寫在前面
我們知道webpack其實不僅是javascript模塊打包工具,更是整個前端項目即前端工程的模塊打包工具,可以通過webpack去管理前端項目中任意類型的資源文件。
如何加載資源模塊
首先,我們在項目的src目錄下添加一個樣式文件main.css。目錄結構如下:
- |--03-loader
- |--src
- |--main.css
- |--package.json
- |--webpack.config.js
- /* main.css */
- body{
- margin:0 auto;
- padding:0 20px;
- max-width:800px;
- background:yellow;
- }
接下來,在webpack.config.js配置中的入口文件路徑進行更改為main.css文件路徑,執行webpack直接進行打包css資源文件。
- const path = require("path")
- module.exports = {
- // 樣式文件路徑
- entry:"src/main.css",
- output:{
- filename:"bundle.js",
- path:path.join(__dirname,"output")
- },
- mode:"none"
- }
如果我們不進行其他的任何配置,此時直接執行打包命令,會報錯提示我們報錯,因為只能是使用js文件作為打包入口。之所以會這樣,那是因為在webpack中默認解析的是js語法,而對于非js語法需要先進行Loader,再在配置文件中另外進行配置loader。
css文件通過css-loader進行處理,再提交給webpack進行打包生成js文件。
- $ npm i css-loader -D
但是,當你此時執行打包命令后,嘗試在你頁面中使用生成bundle.js文件,會發現剛剛的main.css模塊并沒有起作用,那么我們需要額外添加一個style-lodaer加載器,這樣就能正常工作了。樣式沒有生效的原因是:css-loader只會把css模塊加載到js代碼中,而不會直接使用此模塊。
那么,在你安裝完style-lodaer后,將配置文件中的use屬性修改為數組,將style-lodaer也配置進去。因為loader數組的加載順序是自下而上的,所以style-lodaer應該配置在css-loader上面。
- //main.js
- import "./style.css"
- console.log("hello yichuan");
- /* style.css */
- body{
- margin:0 auto;
- padding:0 20px;
- max-width:800px;
- background:yellow;
- }
loader加載器是整個webpack打包配置的核心,因為需要通過它去實現任意類型文件的打包,這樣最后都進行打包生成了js文件。
那么,為什么webpack要在js中載入css文件,而不是將樣式文件和行為進行分離?
這是因為,真正需要其他資源的并不是整個項目中,而是某個模塊需要使用。
假設在進行頁面開發某個局部功能時,需要使用到一個樣式模塊和一個圖片文件,如果你還是將這些資源單獨引入到html文件中,然后再到js中添加對應的邏輯代碼,試想如果后期不需要這個局部功能,那么就需要同時刪除JS中的代碼和html中的資源文件引入,也就是需要同時維護多條線。然而,此時你遵循webapck的導入設計,所有資源加載都是通過js代碼控制,那么后期只需要維護js代碼就行。
為什么要建立這種JS文件導入其他資源的依賴關系,這是因為:
邏輯上比較合理:因為JS確實需要這些資源文件配合才能實現整體功能
配合webapck這類工具的打包:能夠確保在上線時,資源不會缺失,而且都是必要的。
接下來,我們進行簡易的loader開發,目標是實現對md文件的打包。
- // index.js
- import mrakdown from "hello.md"
- <!-- hello.md -->
- ## 你好呀
- //md-loader.js
- const md = require("./hello.md")
- module.exports = source => {
- // 加載到的模塊內容
- console.log("加載到的模塊內容==>",source);
- // 返回值就是最終打包的結果
- return "你好呀"
- }
- //webpack.config.js
- const path = require("path")
- module.exports = {
- // 樣式文件路徑
- entry:"./src/index.js",
- output:{
- filename:"bundle.js"
- },
- mode:"none",
- module:{
- rules:[{
- test:/\.md$/,//根據打包過程中所遇文件路徑記性匹配是否使用此loader
- use:"./md-loader"//指定具體使用的loader
- }]
- }
- }
此時執行打包命令后報錯,提示我們加載對應的loader。這是因為打包的每個loader形成一個鏈條,每個loader都依賴于另一個loader的引入,最終打包出來的必須是js文件。對此,我們有處理方法:
- 將我們自定義的md-laoder加載器的輸出設置為js語法
- 安裝對應的loader加載器
- module.exports = source => {
- // 加載到的模塊內容
- console.log("加載到的模塊內容==>",source);
- // 返回值就是最終打包的結果
- return "console.log('你好呀')";
- }
那么當我們使用合適的Loader加載器將md文件解析為html模塊,需要先進行安裝marked,安裝完后在md-loader.js導入模塊,然后進行解析。
- $ npm i marked
- //./md-loader.js
- const marked = require("marked")
- module.exports = source => {
- // 1.將md文件轉為html字符串
- const html = marked(source);
- return `export default ${JSON.stringify(html)}`
- }
參考文章
《webpack原理與實踐》
《webpack中文文檔》
寫在最后
loader機制是webpack核心內容,因為有了loader機制webpack才能足以支撐整個前端項目模塊化,實現通過webpack去加載任何想要的資源。