Webpack打包TypeScript類庫的實踐

一 : package.json
node

{
  "name": "libDemo",
  "version": "1.0.0",
  "description": "測試打包",
  "main": "./dist/mainLib.js",
  "typings": "./dist/mianLib.d.ts",
  "private": true,
  "scripts": {
    "build": "webpack --mode=development",
    "publish": "webpack --mode=production"
  },
  "files": [
    "dist"
  ],
  "repository": {
    "type": "",
    "url": ""
  },
  "keywords": [
    "mainLib"
  ],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-eslint": "^10.1.0",
    "clean-webpack-plugin": "^1.0.1",
    "copy-webpack-plugin": "^4.4.2",
    "filemanager-webpack-plugin": "^2.0.4",
    "ts-loader": "^4.4.1",
    "typescript": "^3.7.2",
    "uglifyjs-webpack-plugin": "^1.1.1",
    "webpack": "^4.41.4",
    "webpack-cli": "^4.2.0"
  },
  "dependencies": {
    "uglify-es": "^3.3.9",
    "webpack-dts-bundle": "0.0.2"
  }
}

二 ,tsconfig.jsonwebpack

{
  "compileOnSave": false,
  "compilerOptions": {
    "target": "es5",
    "outDir": "./dist/",
    "sourceMap": true,
    "module": "commonjs",
    "noImplicitAny": true,
    "noUnusedParameters": true,
    "declaration": true,
    "declarationDir": "./",
    "suppressImplicitAnyIndexErrors": true,
//    "alwaysStrict": true,
    "removeComments": true,
    "lib": [
      "es6",
      "dom",
      "es2015.promise"
    ],
    "types": [
    ],
    "typeRoots": [
      "./node_modules/@types",
      "./typings",
      "types"
    ]
  },
  "include": [
    "src"
  ],
  "exclude": [
    "node_modules",
    "dist"
  ]
}

三,webpack.config.jses6

// webpack.config.js

const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin');
//const uglifyJsPlugin = require('uglifyjs-webpack-plugin');
//const CopyWebpackPlugin = require('copy-webpack-plugin');
// const WriteFilePlugin = require('write-file-webpack-plugin');
const FileManagerPlugin = require('filemanager-webpack-plugin');
let pathsToClean = ['dist'];
const cleanOptions = {
    root: path.resolve(__dirname),
    //exclude: ['dist'],
    verbose: true,
    dry: false
};

module.exports = {
    entry: {
        "mainLib" : [
            "./src/Main.ts",
            "./src/SubMain.ts",
            "./src/cmd/A.ts"
        ]
    },
    devtool: "source-map",
    output: {
        filename: '[name].js',//// 生成的fiename須要與package.json中的main一致
        path: path.resolve(__dirname, 'dist'),
        libraryTarget: "commonjs",//umd
    },
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                loader: 'ts-loader',
                options: {
                    //// 指定特定的ts編譯配置,爲了區分腳本的ts配置
                    configFile: path.resolve(__dirname, './tsconfig.json'),
                },
                exclude: /node_modules/,
            },
        ]
    },
    resolve: {
        extensions: [".tsx", ".ts", ".js"]
    },
    plugins: [
        //清理dist
        new CleanWebpackPlugin(
            pathsToClean,
            cleanOptions
        ),
        new FileManagerPlugin({
            onEnd: {
                copy: [{source: './dist/mainLib.js', destination: './dist/mainLib.min.js'}],
            }
        }),
        new DtsBundlePlugin()
        //複製
        // new CopyWebpackPlugin([
        //     {
        //         from: __dirname+  '\\dist\\mainLib.js',
        //         to: __dirname+ '\\dist\\mainLib.min.js'
        //     }
        // ]),
        // new WriteFilePlugin({  })
        //壓縮
        // new uglifyJsPlugin({
        //     parallel: false,
        //     include: /min\.js$/
        // })
        // new CleanWebpackPlugin(pathsToClean, cleanOptions2Main)
    ]
};

function DtsBundlePlugin() { }
DtsBundlePlugin.prototype.apply = function (compiler) {
    compiler.plugin('done', function () {
        var dts = require('dts-bundle');
        var rootDir = path.resolve(__dirname);
        dts.bundle({
            name: 'a',
            prefix: "___",
            main: rootDir + '/dist/**/*.d.ts',
            out: rootDir + '/dist/mainLib.d.ts',
            removeSource: true,
            outputAsModuleFolder: true,
            exclude: [],
            headerText: " \n@author Aonaufly \n@email Aonaufly@126.com\n"
        });
    });
};


四, 有2個地方須要修改web

1,node_modules ->dst-bundle->lib->index.jstypescript

mergeModulesLines() 方法 , 修改此方法的主要目的是爲了在.d.ts文件夾中 , 在module前面加declarejson

function mergeModulesLines(lines) {
    var i = (outputAsModuleFolder ? '' : indent);
    // lines[0] = " declare  " + lines[0];
    for( let i = 0; i < lines.length; i ++ ){
        if( (lines[i] + "").indexOf( "module" ) >= 0 ){
            const index = (lines[i] + "").indexOf( "module" );
            if( index == 0 ){
                lines[i] = "declare " + lines[i];
            }else{
                if( (lines[i] + "").indexOf( "declare module" )  < 0 ){
                    const  arr = ( lines[i] + "" ).split("module");
                    lines[i] = arr[0] + " declare module " + arr[1];
                }
            }
            break;
        }
    }
    return (lines.length === 0 ? '' : i + lines.join(newline + i)) + newline;
}

2,node_modules->filemanager-webpack-plugin->node_modules->fs-extra->lib->copy->copy.jspromise

const Uglify = require('uglify-es')//引入babel

修改 copyFile()方法,主要做用,當filemanager-webpack-plugin生成了mainLib.min.js後,讀取mainLib.js代碼數據,並使用uglify-esapp

進行min壓縮,把壓縮後的代碼寫入mainLib.min.js。dom

function copyFile (srcStat, src, dest, opts, cb) {
  if (typeof fs.copyFile === 'function') {
    return fs.copyFile(src, dest, err => {
      if (err) return cb(err)
      if( (dest + "").indexOf( "min") > 0 ){
        // let result = UglifyJS.minify({ 'js.js'  , fs.readFile( src )});
        nodefs.readFile(src, 'utf-8' ,(err, context) => {
          context = context.replace( /\/\*\*\*\*\*\*\//g , '');
          context = context.replace(/\/\**\S\*\//g , '');
          let result = Uglify.minify({ 'js.js'  : context} , {
            compress:{
              toplevel: true,
              passes: 3,
              drop_console : true,
              loops: true,
              collapse_vars: true
            }

          });
          let data = (result.code + "").replace( /\\n/g , '' );
          data = data.replace( /\\r/g ,'' );
          data = data.replace(/\s+/g , ' ');
          nodefs.writeFile( dest , data, ( err ) => {
            // console.log('寫入成功!');
          } );
        })
      }
      return setDestModeAndTimestamps(srcStat, dest, opts, cb)
    })
  }
  return copyFileFallback(srcStat, src, dest, opts, cb)
}

這樣能夠完美生成 一個JS 加 對應的min.js 另外加一個申明文件(.d.ts)

B01.png目前本人只能想到這一手,將3個文件都到一次性導出來,各位讀者有更好的方案,請不吝賜教!

相關文章
相關標籤/搜索