主頁 > 軟體設計 > Webpack入門 - 從0開始搭建專案配置

Webpack入門 - 從0開始搭建專案配置

2020-12-19 08:12:58 軟體設計

前言

webpack 作為前端最知名的打包工具,能夠把散落的模塊打包成一個完整的應用,大多數的知名框架 cli 都是基于 webpack 來撰寫,這些 cli 為使用者預設好各種處理配置,使用多了就會覺得理所當然,也就不在意是內部是如何配置,如果脫離 cli 開發,可能就無從下手了,

最近在開發一些單頁專案時,出于需求便開始從頭搭建專案配置,本文主要分享搭建時用到的配置,

準備作業

快速生成 package.json:

npm init -y

必不可少的 webpack 和 webpack-cli:

npm i webpack webpack-cli -D

入口、出口

webpack 的配置會統一放到組態檔中去管理,在根目錄下新建一個名為 webpack.config.js 的檔案:

const path = require('path')

module.exports = {
  entry: {
    main: './src/js/main.js'
  },
  output: {
    // filename 定義打包的檔案名稱
    // [name] 對應entry配置中的入口檔案名稱(如上面的main)
    // [hash] 根據檔案內容生成的一段隨機字串
    filename: '[name].[hash].js',
    // path 定義整個打包檔案夾的路徑,檔案夾名為 dist
    path: path.join(__dirname, 'dist')
  }
}

entry 配置入口,可配置多個入口,webpack 會從入口檔案開始尋找相關依賴,進行決議和打包,

output 配置出口,多入口對應多出口,即入口配置多少個檔案,打包出來也是對應的檔案,

修改 package.json 的 script 配置:

"scripts": {
  "build": "webpack --config webpack.config.js"
}

這樣一個最簡單的配置就完成了,通過命令列輸入 npm run build 就可以實作打包,

配置項智能提示

webpack 的配置項比較繁雜,對于不熟悉的同學來說,如果在輸入配置項能夠提供智能提示,那開發的效率和準確性會大大提高,

默認 VSCode 并不知道 webpack 配置物件的型別,通過 import 的方式匯入 webpack 模塊中的 Configuration 型別后,在書寫配置項就會有智能提示了,

/** @type {import('webpack').Configuration} */
module.exports = {

}

環境變數

一般開發中會分開發和生產兩種環境,而 webpack 的一些配置也會隨環境的不同而變化,因此環境變數是很重要的一項功能,使用 cross-env 模塊可以為組態檔注入環境變數,

安裝模塊 cross-env

npm i cross-env -D

修改 package.json 的命令傳入變數:

"scripts": {
  "build": "cross-env NODE_ENV=production webpack --config webpack.config.js"
}

在組態檔里,就可以這樣使用傳入的變數:

module.exports = {
  devtool: process.env.NODE_ENV === 'production' ? 'none' : 'source-map'
}

同理,在專案的 js 內也可以使用該變數,

設定 source-map

該選項能設定不同型別的 source-map ,代碼經過壓縮后,一旦報錯不能準確定位到具體位置,而 source-map 就像一個地圖, 能夠對應源代碼的位置,這個選項能夠幫助開發者增強除錯程序,準確定位錯誤,

為了體驗它的作用,我在源代碼中故意輸出一個不存在的變數,模擬線上錯誤:

在預覽時,觸發錯誤:

很明顯錯誤的行數是不對應的,下面設定 devtool 讓 webpack 在打包后輸出 source-map 檔案,用于定位錯誤,

module.exports = {
  devtool: 'source-map'
}

再次觸發錯誤,source-map 檔案起作用準確定位到代碼錯誤的行數,

source-map 一般只在開發環境用于除錯,上線時絕對不能帶有 source-map 檔案,這樣會暴露源代碼,下面通過環境變數來正確設定 devtool 選項,

module.exports = {
  devtool: process.env.NODE_ENV === 'development' ? 'source-map' : 'none'
}

devtool 的可選項很多,它的品質和生成速度有關聯,比如只定位到某個檔案,或者定位到某行某列,相應的生成速度會快或更慢,可以根據你的需求進行選擇,更多可選值請查看 webpack 檔案

loader 與 plugin

loader 與 plugin 是 webpack 的靈魂,如果把 webpack 比作成一個食品加工廠,那么 loader 就像很多條流水線,對食品原料進行加工處理,plugins 則是在原有的功能上,添加其他功能,

loader 基本用法

loader 配置在 module.rules 屬性上,

module.exports = {
  module: {
    rules: []
  }
}

下面來簡單了解下 loader 的規則,一般常用的就是 testuse 兩個屬性:

  1. test 屬性,用于標識出應該被對應的 loader 進行轉換的某個或某些檔案,
  2. use 屬性,表示進行轉換時,應該使用哪個 loader,
rules: [
  {
    test: /\.css$/,
    use: ['css-loader']
  }
]
// 也可以寫為
rules: [
  {
    test: /\.css$/,
    loader: 'css-loader'
  }
]

上面例子是匹配以 .css 結尾的檔案,使用 css-loader 決議,

當有些 loader 可傳入配置時,可以改為物件的形式:

rules: [
  {
    test: /\.css$/,
    user: [
      {
        loader: 'css-loader',
        options: {}
      }
    ]
  }
]

最后需要記住多個 loader 的執行是嚴格區分先后順序的,從右到左,從下到上,

plugin 基本用法

plugin 配置在 plugins 屬性上,

module.exports = {
  plugins: []
}

一般 plugin 會暴露一個建構式,通過 new 的方式使用,plugin 的引數則在呼叫函式時傳入,plugin 命名一般是將按照原名轉為大駝峰,

const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
  plugin: [
    new CleanWebpackPlugin()
  ]
}

生成 html 檔案

沒有經過任何配置的 webpack 打包出來只有 js 檔案,使用插件 html-webpack-plugin 可以自定義一個 html 檔案作為模版,最終 html 會被打包到 dist 中,而 js 也會被引入其中,

安裝 html-webpack-plugin:

npm i html-webpack-plugin -D

配置 plugins:

const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  plugins: {
    // 使用html模版
    new HtmlWebpackPlugin({
      // 配置html標題
      title: 'home',
      // 模版路徑
      template: './src/index.html',
      // 壓縮
      minify: true
    })
  }
}

此時想要配置的標題生效還需要在 html 中為 title 標簽插值:

<title><%= htmlWebpackPlugin.options.title %></title>

除了 title 外,還可以配置諸如 meta 標簽等,

多頁面

上面的使用方法,在打包后只會有一個 html,對于多頁面的需求其實也很簡單,有多少個頁面就 new 幾次 htmlWebpackPlugin

但是需要注意一點,入口配置的 js 是會被全部引入到 html 的,如果想某個 js 對應某個 html,可以配置插件的 chunks 選項,而且需要配置 filename 屬性,因為 filename 屬性默認是 index.html,同名會被覆寫,

module.exports = {
  entry: {
    main: './src/js/main.js',
    news: './src/js/news.js'
  },
  output: {
    filename: '[name].[hash].js',
    path: path.join(__dirname, 'dist')
  },
  plugins: {
    new HtmlWebpackPlugin({
      template: './src/index.html',
      filename: 'index.html',
      minify: true,
      chunks: ['main']
    }),
    new HtmlWebpackPlugin({
      template: './src/news.html',
      filename: 'news.html',
      minify: true,
      chunks: ['news']
    }),
  }
}

es6轉es5

安裝 babel 的相關模塊:

npm i babel-loader @babel/core @babel/preset-env -D

@babel/core 是 babel 的核心模塊,@babel/preset-env 內預設不同環境的語法轉換插件,默認將 es6 轉 es5,

根目錄下創建 .babelrc 檔案:

{
  "presets": ["@babel/preset-env"]
}

配置 loader:

rules: [
  {
    test: /\.js$/,
    exclude: /node_modules/, 
    loader: 'babel-loader'
  }
]

決議 css

安裝 loader:

npm i css-loader style-loader -D

css-loader 只負責決議 css 檔案,通常需要配合 style-loader 將決議的內容插入到頁面,讓樣式生效,順序是先決議后插入,所以 css-loader 放在最右邊,第一個先執行,

rules: [
  {
    test: /\.css$/,
    use: ['style-loader', 'css-loader']
  }
]

但要注意最終打包出來的并不是css檔案,而是js,它是通過創建 style 標簽去插入樣式,

分離css

經過上面的 css 決議,打包出來的樣式會混在 js 中,某些場景下,我們希望把 css 單獨打包出來,這時可以使用 mini-css-extract-plugin 分離 css,

安裝 mini-css-extract-plugin:

npm i mini-css-extract-plugin -D

配置 plugins:

const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/[name].[hash].css',
      chunkFilename: 'css/[id].[hash].css'
    })
  ]
}

配置 loader:

rules: [
  {
    test: /\.css$/,
    use: [
      // 插入到頁面中
      'style-loader',
      {
        loader: MiniCssExtractPlugin.loader,
        options: {
          // 為外部資源(如影像,檔案等)指定自定義公共路徑
          publicPath: '../',
        }
      },
      'css-loader',
    ]
  },
]

經過上面配置后,打包后 css 就會被分離出來,

但要注意如果 css 檔案不是很大的話,分離出來效果可能會適得其反,因為這樣會多一次檔案請求,一般來說單個 css 檔案超過 200kb 再考慮分離,

css瀏覽器兼容前綴

安裝相關依賴:

npm i postcss postcss-loader autoprefixer -D

專案根目錄下新建 postcss.config.js:

module.exports = {
  plugins: [
    require('autoprefixer')()
  ]
}

package.json 新增 browserslist 配置:

{
  "browserslist": [
    "defaults",
    "not ie < 11",
    "last 2 versions",
    "> 1%",
    "iOS 7",
    "last 3 iOS versions"
  ]
}

最后配置 postcss-loader

rules: [
  {
    test: /\.css$/,
    use: [
      'style-loader', 
      'css-loader',
      'postcss-loader'
     ]
  }
]

處理前后對比:

壓縮 css

webpack 內部默認只對 js 檔案進行壓縮,css 的壓縮可以使用 optimize-css-assets-webpack-plugin 來完成,

安裝 optimize-css-assets-webpack-plugin:

npm i optimize-css-assets-webpack-plugin -D

配置 plugins:

const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')

module.exports = {
  plugins: [
    new OptimizeCssAssetsWebpackPlugin()
  ]
}

壓縮結果:

決議圖片

專案中肯定少不了圖片,對于圖片資源,webpack 也有相應的 url-loader 來決議,url-loader 除了決議圖片外,還可以將比較小的圖片可以轉為base64,減少線上對圖片的請求,

安裝 url-loader:

npm i url-loader -D

配置 loader:

rules: [
  {
    test: /\.(jpg|png|jpeg|gif)$/,
      use: [{
        loader: 'url-loader',
        // 小于50k的圖片轉為base64,超出的打包到images檔案夾
        options: {
          limit: 1024 * 50,
          outputPath: './images/',
          pulbicPath: './images/'
        }
    }]
  }
]

配置完成后,只需要在入口檔案內引入圖片使用,webpack 就可以幫助我們把圖片打包出來了,

但有時候,圖片鏈接是直接寫到 html 中,這種情況 url-loader 無法決議,不慌,使用 html-loader 能完成這項需求,

rules: [
  {
    test: /\.(html)$/,
    use: [{
      loader: 'html-loader',
      options: {
        // 壓縮html模板空格
        minimize: true,
        attributes: {
          // 配置需要決議的屬性和標簽
          list: [{
            tag: 'img',
            attribute: 'src',
            type: 'src',
          }]
        },
      }
    }]
  },
]

注意這里 html-loader 只是起到決議的作用,需要配合 url-loader 或者 file-loader 去使用,也就是說決議模板的圖片鏈接后,還是會走上面所配置的 url-loader 的流程,

還有一點,使用 html-loader 后, html-webpack-plugin 在 html 中的插值會失效,

其他型別資源決議

決議其他資源和上面差不多,不過這里用到的是 file-loaderfile-loaderurl-loader 主要是將檔案上的 import / require() 引入的資源決議為url,并將該資源發送到輸出目錄,區別在于 url-loader 能將資源轉為 base64,

安裝 file-loader:

npm i file-loader -D

配置 loader:

rules: [
  {
    test:/\.(mp3)$/,
    use: [{
      loader: 'file-loader',
      options: {
        outputPath: './music/',
        pulbicPath: './music/'
      }
    }]
  },
  {
    test:/\.(mp4)$/,
    use: [{
      loader: 'file-loader',
      options: {
        outputPath: './video/',
        pulbicPath: './video/'
      }
    }]
  }
]

上面只是列舉了部分,需要決議其他型別資源,參照上面的格式添加配置,

決議 html 中的其他型別資源也和上面同理,使用 html-loader 配置物件的標簽和屬性即可,

devServer 提高開發效率

每次想運行專案時,都需要 build 完再去預覽,這樣的開發效率很低,

官方為此提供了插件 webpack-dev-server,它可以本地開啟一個服務器,通過訪問本地服務器來預覽專案,當專案檔案發生變化時會熱更新,無需再去手動重繪,以此提高開發效率,

安裝 webpack-dev-server

npm i webpack-dev-server -D

配置 webpack.config.js

const path = require('path')

module.exports = {
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    // 默認 8080
    port: 8000,
    compress: true,
    open: true,
  }
}

webpack-dev-server 用法和其他插件不同,它可以不添加到 plugins,只需將配置添加到 devServer 屬性下即可,

添加啟動命令 package.json

{
  "scripts": {
    "dev": "cross-env NODE_ENV=development webpack serve"
  },
}

命令列運行 npm run dev,就可以感受到飛一般的體驗,

復制檔案到 dist

對于一些不需要經過決議的檔案,在打包后也想將它放到 dist 中,可以使用 copy-webpack-plugin

安裝 copy-webpack-plugin:

npm i copy-webpack-plugin -D

配置 plugins:

const CopyPlugin = require('copy-webpack-plugin')

module.exports = {
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          // 資源路徑
          from: 'src/json',
          // 目標檔案夾
          to: 'json',
        }
      ]
    }),
  ]
}

打包前清除舊 dist

打包后檔案一般都會帶有哈希值,它是根據檔案的內容來生成的,由于名稱不同,可能會導致 dist 殘留有上一次打包的檔案,如果每次都手動去清除顯得不那么智能,利用 clean-webpack-plugin 可以幫助我們將上一次的 dist 清除,保證無冗余檔案,

安裝 clean-webpack-plugin

npm i clean-webpack-plugin -D

配置 plugins:

const CleanWebpackPlugin = require('clean-webpack-plugin')

module.exports = {
  plugins: [
    new CleanWebpackPlugin()
  ]
}

插件會默認清除 output.path 的檔案夾,

自定義壓縮選項

webpack 從 v4.26.0 開始內置的壓縮插件變為 terser-webpack-plugin,如果沒有其他需求,自定義壓縮插件也盡量保持與官方的一致,

安裝 terser-webpack-plugin:

npm i terser-webpack-plugin -D

配置 plugins:

const TerserPlugin = reuqire('terser-webpack-plugin')

module.exports = {
  optimization: {
    // 默認為 true
    minimize: true,
    minimizer: [
        new TerserPlugin()
    ]
  },
}

插件壓縮配置可以查閱 terser-webpack-plugin 檔案,在呼叫時自定義選項,

像上面的 css 壓縮插件也可以添加到 optimization.minimizer,與配置到 plugins 的區別是,配置到 plugins 的插件在任何情況都會去執行,而配置到 minimizer 中,只有在 minimize 屬性開啟時才會作業,

這樣做的目的便于通過 minimize 屬性來統一控制壓縮,

const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
const TerserPlugin = reuqire('terser-webpack-plugin')

module.exports = {
  optimization: {
    // 默認為 true
    minimize: true,
    minimizer: [
        new TerserPlugin(),
        new OptimizeCssAssetsWebpackPlugin()
    ]
  },
}

注意如果你提供 minimizer 選項而沒有使用 js 壓縮插件,即使 webpack 內置 js 壓縮,打包出來的 js 也不會被壓縮,因為 webpack 壓縮配置會被 minimizer 覆寫,

排查錯誤的建議

在使用 webpack 的程序中,這玩意偶爾會有些奇奇怪怪的報錯,

下面是我遇到的一些錯誤以及解決方法(僅供參考并不是萬能法則):

  1. 一些 loader 和 plugin 在使用時,會依賴 webpack 的版本,如果使用程序發生錯誤,檢查是否有版本不兼容的問題,可以嘗試降一個版本,
  2. 重新安裝依賴,有可能下載程序中,一些依賴會沒裝上,
  3. 查看使用檔案,不同版本所傳入的選項屬性可能會不一樣(被坑過) ,

還有注意控制臺的提示,一般根據錯誤提示都能猜出大概是什么問題,

依賴版本和完整配置

專案結構:

依賴版本:

{
    "@babel/core": "^7.12.3",
    "@babel/preset-env": "^7.12.1",
    "autoprefixer": "^10.0.1",
    "babel-loader": "^8.1.0",
    "clean-webpack-plugin": "^3.0.0",
    "copy-webpack-plugin": "^6.3.0",
    "cross-env": "^7.0.2",
    "css-loader": "^5.0.0",
    "file-loader": "^6.2.0",
    "html-loader": "^1.3.2",
    "html-webpack-plugin": "^4.5.0",
    "mini-css-extract-plugin": "^0.9.0",
    "postcss": "^8.1.6",
    "postcss-loader": "^4.0.4",
    "style-loader": "^2.0.0",
    "url-loader": "^4.1.1",
    "webpack": "^4.44.2",
    "webpack-cli": "^4.2.0",
    "webpack-dev-server": "^3.11.0"
}

webpack.config.js:

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CopyPlugin = require('copy-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

/** @type {import('webpack').Configuration} */
module.exports = {
  devtool: process.env.NODE_ENV === 'development' ? 'source-map' : 'none',
  entry: {
    main: './src/js/main.js'
  },
  output: {
    filename: '[name].[hash].js',
    path: path.join(__dirname, 'dist')
  },
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    port: 8000,
    compress: true,
    open: true,
  },
  plugins: [
    // 清除上一次的打包內容
    new CleanWebpackPlugin(),
    // 復制檔案到dist
    new CopyPlugin({
      patterns: [
        {
          from: 'src/music',
          to: 'music',
        }
      ]
    }),
    // 使用html模版
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: true
    }),
    // 分離css
    new MiniCssExtractPlugin({
      filename: 'css/[name].[hash].css',
      chunkFilename: 'css/[id].[hash].css'
    }),
    // 壓縮css
    new OptimizeCssAssetsWebpackPlugin()
  ],
  module: {
    rules: [
      // 決議js(es6轉es5)
      {
        test: /\.js$/,
        exclude: /node_modules/, 
        loader: 'babel-loader'
      },
      {
        test: /\.css$/,
        use: [
          'style-loader',
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: '../',
            }
          },
          'css-loader',
          'postcss-loader'
        ]
      },
      {
        test: /\.(html)$/,
        use: [{
          // 主要為了決議html中的img圖片路徑 需要配合url-loader或file-loader使用
          loader: 'html-loader',
          options: {
            attributes: {
              list: [{
                tag: 'img',
                attribute: 'src',
                type: 'src',
              },{
                tag: 'source',
                attribute: 'src',
                type: 'src',
              }]
            },
            minimize: true
          }
        }]
      },
      // 決議圖片
      {
        test: /\.(jpg|png|gif|svg)$/,
        use: [{
          loader: 'url-loader',
          // 小于50k的圖片轉為base64,超出的打包到images檔案夾
          options: {
            limit: 1024 * 50,
            outputPath: './images/',
            pulbicPath: './images/'
          }
        }]
      },
      // 決議其他型別檔案(如字體)
      {
        test: /\.(eot|ttf)$/,
        use: ['file-loader']
      },
      {
        test: /\.(mp3)$/,
        use: [{
          loader: 'file-loader',
          options: {
            outputPath: './music/',
            pulbicPath: './music/'
          }
        }]
      }
    ]
  },
}

最后

由于單頁專案簡單,配置項比較樸實無華,本文主要是些基礎配置,不過套路都差不多,根據專案的需求去選擇 loader 和 plugin,更多的還是要了解這些插件的作用和使用方法,以及其他常用的插件,

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/237057.html

標籤:架構設計

上一篇:springcloud 專案原始碼 微服務 分布式 flowable作業流 vue.js html 跨域 前后分離

下一篇:About inventory check

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more