更優雅的使用 Parcel 進行前端專案的打包

超級大柱子發表於2018-07-22

Parcel 有著開箱即用的特性, 為我們初始化工程省卻了許多時間, 但是零配置的特性導致我們比較不方便進行一些預處理, 這篇文章就帶領讀者解決一些我們常會遇到的一些問題. 只需要很簡單的新增幾個引數,就可以滿足我們大部分的特殊情況.

在去年, Parcel 沒有支援 SourceMap 的特性, 導致於無法進行斷點除錯, 從而很多團隊沒有在生產中使用 Parcel, 現在 Parcel 已經支援 SourceMap 的特性, 再加上可以很方便的編寫外掛去填補一些自定義的功能, 所以 Parcel 我認為已經可以在新專案的生產中投入使用了.

本文作者簡單的編寫了一個 parcel-plugin-change-file 外掛示例, 來滿足下面的功能, 具體使用請繼續閱讀文章內容.

本文不會對 Parcel 的基礎使用再多做解釋, 如果您還沒有接觸過 Parcel ,請先去了解: Parcel 官方文件-快速開始

如何跳過不需要打包的檔案?

如果我們使用 parcel index.html 命令, Parcel 會自動識別html中的引用,如果是http://就不會進行打包處理, 如果是本地檔案,就會識別成Assets物件,進行打包.

如果我們需要跳過對本地檔案的打包, 我們可以使用 parcel-plugin-change-file 外掛

$ yarn add -D parcel-plugin-change-file
複製程式碼

在 index.html中新增 <!--[ your-code ]--> , 注意這裡有兩個中括號.

<body>
  <!--[ <script src="lodash.min.js"></script> ]-->
</bodt>
複製程式碼

當專案編譯結束之後, 該外掛會把 <!--[ your-code ]--> 的註釋內容開啟,從而跳過 Parcel 的打包檢測.

<body>
  <script src="lodash.min.js"></script>
</bodt>
複製程式碼

如何對html進行修改?

例如, 我們嘗試根據 package.json 中的資訊修改 index.htmltitle

在專案跟路徑建立 parcel-plugin-change-file.js 檔案

const package = require('./package.json')
module.exports = {
  html: [package.name],
};
複製程式碼

src/index.html 中新增 <!-- parcel-plugin-change-file-i --> , 其中 i 對應之前 html 物件中的陣列下標, 這裡我們只有一個, 所以用 0

<header>
  <title><!-- parcel-plugin-change-file-0 --></title>
</header>
複製程式碼

當專案編譯結束之後, 該外掛會把 package.json 中的 name 資訊插入到 title

<body>
  <title>Parcel優雅配置</title>
</bodt>
複製程式碼

如何在parcel打包結束之後拷貝一些檔案到打包目錄?

例如, 某些情況, 我們不需要 Parcel 幫我們處理 png 圖片, 我們希望直接使用圖片路徑:

class Banner extends React.Componet {
  render(){
    return <div style={{
      backgoundImage:'img/test.png'
    }} ></div>
  }
}
複製程式碼

那我們就需要在打包之後再把圖片拷貝到相應的路徑.

還是確保parcel-plugin-change-file 已被安裝, 然後在專案跟路徑建立parcel-plugin-change-file.js

module.exports = {
  copy: ['src/assets', 'src/documents'],
};
複製程式碼

正常執行 Parcel 打包指令碼, 就會把 src/assetssrc/documents子內容拷貝到打包輸出的跟路徑

$ parcel src/index.html
複製程式碼

如何達到和 webpack.DllPlugin 一樣的預先編譯的效果呢?

Webpack 的 DllPlugin 外掛可以把一些不常進行修改的庫提前編譯成一個檔案, 然後在專案裡引用, 經過配置webpack不會再次編譯這些已經編譯過的檔案.這樣可以大大的加速平時編譯的時間. 從而趕上 Parcel 的打包速度.

而在 Parcel 中,也可以可以把一些不常進行修改的庫提前編譯成一個檔案, 這樣可以在 Parcel 原本就快速的編譯前提下再減去絕大部分的編譯內容, 從而極大的加速平時編譯的時間, 不過就只能使用全域性物件引用了.

在Parcel專案中, 是可以使用全域性物件的, 例如我們在html中引入一個lodash:

<body>
    <script src="https://cdn.bootcss.com/lodash.js/4.17.9/lodash.min.js"></script>
</body>
複製程式碼

此時, 在專案中不需要import _ from 'lodash', 可以識別全域性_物件的

console.log(_.map)  //可以列印出 _.map 方法
複製程式碼

有了以上知識點,我們可以這樣做:

  1. 建立一個預先需要打包的檔案:
// dll/default.js
// 假設這些庫是自己編寫的庫, 需要在預編譯, 並且在全域性引用
import _ from 'lodash';
import Immutable from 'immutable';

// 暴露到全域性物件中
window['_'] = _;
window['Immutable'] = Immutable;

複製程式碼
  1. 使用Parcel進行打包, 其中changeFile=false 是不使用 parcel-plugin-change-file 外掛:
$ changeFile=false parcel build dll/default.js -d src/dll -o defalut.min.js
複製程式碼

以上 default.min.js 已經建立好了, 接下來是在平時 Parcel 的專案中使用它

  1. 我們需要在 src/index.html 裡引入 src/dll/default.min.js
<head>
    <!--[ <script src="default.min.js"></script> ]-->
</head>
複製程式碼
  1. 建立parcel-plugin-change-file.js
module.exports = {
  copy: ['src/dll'],
};
複製程式碼
  1. 大功告成,可以在專案裡直接使用之前 default.min.js 中暴露在 window 下的全域性物件
// src/index.js
_.map(_.range(500), v=>{
  console.log(`hello:${v}`);
})
複製程式碼
  1. 如果需要有提示, 需要編寫 .d.ts 檔案, 然後在專案中引入

這一塊知識點請查閱 typescript Declaration Files 文件

/// <reference path="./your-edit.d.ts"/>
複製程式碼

啟動專案:

$ parcel src/index.html
複製程式碼

最後, 如果這篇文章有幫到你, 歡迎 Star: parcel-plugin-change-file

相關文章