這是我參與更文挑戰的第9天,活動詳情查看: 更文挑戰javascript
回顧前兩篇文章中,咱們從一個現成的webpack-template
中,逐步逐步地修改構建出了一個組件調試的頁面,當組件調試沒問題以後,咱們就要對組件進行一個打包操做讓其餘用戶可使用。css
若是尚未閱讀第一,二篇的小夥伴們, 請點擊閱讀: 手把手教你使用webpack打包前端組件(一)html
執行npm run build
命令進行項目打包 ~ ~vue
打包後分別有html
和js
文件,咱們使用編輯器打開Drag.html
,發現html中已經幫咱們引入了Drag.js
了,其實在這裏邊它已經引入better-draggable-ball
了,再使用瀏覽器打開後發現拖拽球是能夠被正常顯示出來的。java
當咱們從新建立一個HTML
文件,引入better-draggable-ball
時,再按原來ts
中的寫法會發現:node
Drag is not definedwebpack
難道咱們只能引入已經配置好配置項的Drag麼???es6
強大的webpack
也給咱們提供了output.library
選項,webpack
打包時能夠將你的項目做爲一個庫來導出web
咱們修改webpack.config.ts
配置文件,將咱們的項目中的better-draggable-ball
做爲一個庫來導出
在web
entry: {
'better-draggable-ball': './src/components/better-draggable-ball/index.ts'
},
複製代碼
在output
屬性中添加library
屬性。
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
clean: true,
library:'betterDraggableBall',
},
複製代碼
將plugins
屬性中的HtmlWebpackPlugin
進行刪除,由於咱們已經不須要導出HTML
文件了,只須要導出js
文件讓其用戶去引用就能夠了。
plugins: [
new ESLintPlugin({
extensions: ['js', 'ts'],
exclude: '/node_modules/',
}),
],
複製代碼
附上完整的webpack.config.ts
配置文件代碼:
import * as path from 'path';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import ESLintPlugin from 'eslint-webpack-plugin';
import * as webpack from 'webpack';
const config: webpack.Configuration = {
mode: 'production',
entry: {
'better-draggable-ball': './src/components/better-draggable-ball/index.ts', // better-draggable-ball 插件
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
clean: true,
library: 'betterDraggableBall'
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: [
// 將 JS 字符串生成爲 style 節點
'style-loader',
// 將 CSS 轉化成 CommonJS 模塊
'css-loader',
// 將 Sass 編譯成 CSS
'sass-loader',
],
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
plugins: [
new ESLintPlugin({
extensions: ['js', 'ts'],
exclude: '/node_modules/',
}),
],
};
export default config;
複製代碼
接下來咱們再打包一下,能夠看到此次dist
文件夾中只輸出了better-draggable-ball
文件。
接下來,咱們在dist
文件夾中建立一個test.html
文件,利用script
標籤引入一下,而後使用console.log
來打印下betterDraggableBall
看看裏邊是什麼?
很明顯,打印出來的是個Object,裏邊只有一個default
的函數,咱們打印下試試。
是一個函數,咱們仔細一看,誒?這不是咱們的Drag
麼?
咱們試試看能不能new一下試試 。
!!! 注意:打包後 庫的位置是在
.default
中 !!!
<script src="../dist/better-draggable-ball.js"></script>
<script> window.onload = () => { let DragDom = document.getElementById('drag') Drag = new betterDraggableBall.default(DragDom) console.log(Drag); } </script>
複製代碼
在webpack.config.ts
中配置下library
,讓default
中的數據做爲默認導出對象,type屬性是配置庫的暴露方式,以後再打包一下
library: {
name: 'betterDraggableBall',
type: 'umd',
export: 'default',
},
複製代碼
打印下betterDraggableBall
對象,此次咱們能夠看到沒有default
這個屬性了,而是將default
裏的內容放到了betterDraggableBall
對象根部了,也就是說如今能夠直接直接new
一個betterDraggableBall
類了
咱們如今只達到了能夠經過script
標籤來引入組件了
CommonJS
格式的 js
文件UMD
格式的 js
文件ESM
格式的js
文件這裏給你們簡單的講下這些格式
CommonJS
是服務器端模塊的規範,Node.js採用了這個規範。,主要語法:好比加載模塊使用的是require
方法,導出模塊使用的是export
,CommonJS
加載模塊是同步的,因此只有加載完成才能執行後面的操做。
AMD
全稱 Asyncchronous Module Definition
,通常應用在瀏覽器端(這是與 CommonJS
規範最大的不一樣點),最著名的 AMD 加載器是 RequireJS
。目前因爲 webpack
的流行, AMD
這一模塊化方案已逐漸退出市場。
UMD
是AMD
和CommonJS
的糅合,以及最傳統的全局變量模式。全局變量模式便是把庫的入口掛載在一個全局變量(window.xxx
)上,頁面上的任何位置都能隨時取用,屬於最傳統的 js
插件加載方案,它的出現也是解決跨平臺的問題。UMD先判斷是否支持Node.js的模塊(exports)是否存在,存在則使用Node.js模塊模式。在判斷是否支持AMD(define是否存在),存在則使用AMD方式加載模塊。
esm
即 es6 模塊,在以前經常使用的是 CommonJS
和基於 AMD
的其餘模塊系統,ES Modules 的關鍵字是 import
和 export
,也是目前最流行的一種導入方式。
咱們須要修改webpack
的配置文件,以前咱們打包項目都是使用單獨的一種配置方式,可是咱們如今須要導出多種類型文件,這時webpack
給咱們提供了導出多種配置方式的寫法(webpack
3.1.0 起支持),把webpack.config.ts
修改以下:
import * as path from 'path';
import { Configuration as webpackConfiguration } from 'webpack';
import ESLintPlugin from 'eslint-webpack-plugin';
const outputConfig: webpackConfiguration[] = [
{
output: {
path: path.resolve(__dirname, 'dist/commonjs'),
filename: '[name].js',
clean: true,
library: {
name: 'betterDraggableBall',
type: 'commonjs',
export: 'default',
},
},
},
{
output: {
path: path.resolve(__dirname, 'dist/umd'),
filename: '[name].js',
clean: true,
library: {
name: 'betterDraggableBall',
type: 'umd',
export: 'default',
},
},
},
{
output: {
path: path.resolve(__dirname, 'dist/module'),
filename: '[name].js',
clean: true,
module: true,
library: {
type: 'module',
},
},
experiments: {
outputModule: true,
},
},
];
const baseConfig: webpackConfiguration = {
mode: 'development',
entry: {
'better-draggable-ball': './src/components/better-draggable-ball/index.ts', // better-draggable-ball 插件
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
{
test: /\.s[ac]ss$/i,
use: [
// 將 JS 字符串生成爲 style 節點
'style-loader',
// 將 CSS 轉化成 CommonJS 模塊
'css-loader',
// 將 Sass 編譯成 CSS
'sass-loader',
],
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
plugins: [
new ESLintPlugin({
extensions: ['js', 'ts'],
exclude: '/node_modules/',
}),
],
};
const config:webpackConfiguration[]|[] = [];
for (let i: number = 0; i < outputConfig.length; i += 1) {
config[i] = Object.assign(outputConfig[i], baseConfig);
}
export default config;
複製代碼
這裏邊,我定義了2個數組,一個是baseConfig
,它用來存放webpackConfig
的基本配置,另一個是outputConfig
,它存放了三種導出方式,分別爲commonjs
,umd
,module
,最後我使用了循環和對象合併方法把基本配置對象和不一樣的output
屬性進行一個合併生成導出一個新的webpackConfig
模塊。
// 合併的語句
const config:webpackConfiguration[]|[] = [];
for (let i: number = 0; i < outputConfig.length; i += 1) {
config[i] = Object.assign(outputConfig[i], baseConfig);
}
複製代碼
咱們打包試一下,看看是否是生成了多種導入方式的文件:
nice!接下來咱們建立一個普通的HTML
文件使用script
標籤引用試一下(umd
)。
<script src="./dist/umd/better-draggable-ball.js"></script>
<script> console.log(betterDraggableBall); </script>
複製代碼
接下來,再試試ESM版本的,這裏我新建了一個vue vite
項目,在項目中的組件中引入它。
// 忽略一些代碼 只列出主要代碼
import Drag from './better-draggable-ball'
setup: () => {
const DragDom=ref<HTMLElement|null>(null)
// 拖拽組件 初始化
onMounted(()=>{
new Drag(DragDom.value, {
defaultPosition: { x: 10, y: 10 },
autoAdsorbent: true,
});
})
return{
DragDom
}
}
複製代碼
一般,開源的插件、庫代碼都會提供兩種版本:
壓縮版的好處:
咱們使用的是webpack5版本以上的,無需terser-webpack-plugin
插件,直接使用就能夠了。
注意:webpack4版本須要安裝!!
npm install terser-webpack-plugin --save-dev 複製代碼
但咱們還須要執行下如下命令,安裝相關聲明文件。
npm i --save-dev @types/terser-webpack-plugin
複製代碼
在baseConfig
的入口屬性中,添加一個better-draggable-ball.min
,做爲壓縮版的文件。
entry: {
'better-draggable-ball': './src/components/better-draggable-ball/index.ts', // better-draggable-ball 插件
'better-draggable-ball.min': './src/components/better-draggable-ball/index.ts', // better-draggable-ball 插件(壓縮版本)
},
// ... ...
複製代碼
在baseConfig
中添加optimization
對象,將含有min
的文件進行壓縮處理。
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: 4,
include: /\.min\.js$/,
terserOptions: {
format: {
comments: false,
},
},
test: /\.js(\?.*)?$/i,
extractComments: false,
}),
],
},
複製代碼
在baseConfig
中添加devtool
屬性,是選擇一種 source map 格式來加強調試過程。不一樣的值會明顯影響到構建(build)和從新構建(rebuild)的速度 ( 官方解釋 )詳細配置請閱讀 Devtool 配置項
devtool:'cheap-module-source-map',
複製代碼
配置完以後,執行npm run build
將項目進行打包 ~ ~
拿打包後的commonjs
版本的插件對比一下,壓縮版本(min.js)比未壓縮版本減小了約50%的體積,這大大提高了瀏覽器加載該插件的速度。
Source map就是一個信息文件,裏面儲存着位置信息。也就是說,轉換後的代碼的每個位置,所對應的轉換前的位置。有了它,瀏覽器開發者工具會調用 source map 來幫助解析,在出錯的時候,除錯工具將直接顯示原始代碼,而不是轉換後的代碼。這無疑在調試過程當中帶來了很大方便。
這是由於上面的配置文件設置了devtool
devtool: 'cheap-module-source-map'
複製代碼
本系列的教程也到此結束了,很感謝你們的觀看,但願這三篇文章對你們有所幫助!
若是你對文章有什麼建議能夠留言在評論區哦
😀😀 關注我,不迷路! 😀😀