1. 程式人生 > >webpack4.0入門配置檔案

webpack4.0入門配置檔案

wepback風頭正火 ,但是公司一直在用gulp,正好趕上年底活動,藉此機會第一次嘗試了webpack,說實話webpack真的很強大,內容一層一層遞進。

這幾天跟著官網跑了一遍,然後寫了自己的配置檔案,因為活動內容不多,很多強大的功能沒有用上,但是相信對於入門來說足夠了。

下面來總結並附上原始碼

當 webpack 處理應用程式時,它會遞迴地構建一個依賴關係圖,其中包含應用程式需要的每個模組,然後將所有這些模組打包成一個或多個 bundle。

webpack支援的模組語法有哪些?

ES6,CommonJs,Amd

webpack和gulp的區別?

Webpack可以通過眾多loader和plugin完成許多gulp上的功能,但Webpack本質在於模組打包,而gulp的本質在於執行任務;使用webpack-stream包可以實現gulp和webpack的搭配使用

核心概念

1.入口:指定使用哪個模組來作為構建內部依賴圖的開始,隨後打包成bundle

2.輸出:定義輸出生產的bundle的位置及檔名;

3.loader:讓webpack可以處理非js模組;loader 可以將所有型別的檔案轉換為webpack 能夠處理的有效模組。

4. 外掛:執行的任務範圍包括從打包優化和壓縮,一直到重新定義環境中的變數,目的在於完成一些loader無法完成的任務。

常用配置項

1.mode: ‘development’|| ‘production’ || ‘none’

2.entry:  array || obj

3.output: {

  path: path.resolve(__dirname, "dist"), // 輸出檔案的目標路徑

  filename:’bundle.js’,// 打包後的檔名

  publicPath: ‘static’// 輸出解析檔案目錄,url相對於html

}

4.module: {

  rules: [

    {

              test: /\.js$/, // 指定使用此loader的檔案

              use: ‘babel-loader’,

              options: { },

              include: /src/, // 匹配項

      exclude: /node_modules/ // 非匹配項

    }

    ]

  }

 5.plugins: […instance]

 6.devServer: {

  host: ‘localhost’,

  port: ‘8080’,

  contentBase: Boolean|| string || array, // 伺服器從哪裡獲取內容

  hot:boolean, // 是否開啟webpack模組熱替換

  open: Boolean, // 是否自動開啟瀏覽器

  proxy: { path: targetUrl}, // 代理

    …others

  }

7.resolve: {

  alias: {

    test: url

    },

  extensions: [.js, .json]

 }

 8.devtool: string || false

   可選值:

  cheap-eval-source-map

  eval-source-map

  cheap-source-map

  source-map

  cheap-module-eval-source-map

  …others

常用loaderplugin

loader

Css-loader:解析css中資源路徑;

Sass-loader:sass轉碼為css

Postcss-loader:使webpack可以用postcss處理css

Px2rem-loader: px轉換為rem

Style-loader:將css以style標籤的形式插入到dom中

Babel-loader:轉碼js以提高相容性

url-loader:圖片轉base64

webpack imagemin-webpack-plugin 壓縮圖片

file-loader:將檔案輸出到輸出目錄並返回檔案路徑

html-loader:處理html中資源路徑                        

eslint-loader:使js支援eslint

plugin

html-webpack-plugin:根據模板匯出html檔案,並注入bundle

DinePlugin: 建立編譯時可以進行配置的全域性變數。

HashedModuleIdsPlugin: 根據模組的相對路徑生成一個四位數的hash作為模組id

extract-text-webpack-plugin:分離css

mini-css-extract-plugin:分離css

uglifyjs-webpack-plugin:壓縮js

optimize-css-assets-webpack-plugin:壓縮css

clean-webpack-plugin: 清空某個目錄

cli常用命令

--config 使用指定的配置檔案

 --env.key=value 指定環境變數

--mode=production 指定模式

--progress 列印編譯進度的百分比

--display-error-details 展示錯誤細節

--define 定義環境變數

-w 觀察檔案變化,變化後重新執行構建流程

--hot 開啟模組熱替換

--json > stats.json 將編譯結果的各種資訊輸出為json檔案

--profile 捕獲編譯時每個步驟的時間資訊

配置檔案編寫

前端常見需求:

  1)       Js壓縮

  2)       Css壓縮

  3)       Css提取

  4)       小圖片轉base64

  5)       Px轉rem

  6)       Css字首新增

  7)       Sass轉碼

  8)       Babel轉碼

  9)       檔名加hash

  10)       檔案編碼格式轉換(常見utf-8與gbk互轉)

  11)       程式碼分離

  12)       Eslint

  13)       模組熱替換

  14)       配置編譯過程的全域性變數

  15)       打包後的程式碼注入html中

1.    常用模組變數

  __dirname:當前資料夾路徑

 2.    常用佔位符

    [hash]:模組識別符號的hash(後拼接:‘:n’可指定長度)

  [chunkhash]: chunk內容的hash(後拼接:‘:n’可指定長度)

  [name]:模組名稱

  [id]: 模組識別符號

3. 配置檔案使用commonjs編寫的,配置型別有下面幾種:

    1) 匯出一個配置物件

  2) 匯出一個函式

  3) 匯出一個promise

程式碼分離

 該功能可以把程式碼分離到不同的 bundle 中,然後可以按需載入或並行載入這些檔案。程式碼分離可以用於獲取更小的 bundle,以及控制資源載入優先順序,如果使用合理,會極大影響載入時間。

程式碼分離的方式:

  1.手動配置多個入口檔案

  2.使用webpack自帶的splitChunks功能

  3.使用import()動態匯入

下面附上自己的web.config.js

//生成html檔案 npm i -D html-webpack-plugin const HtmlWebpackPlugin = require('html-webpack-plugin'); //每次打包前清理目錄檔案 npm i -D clean-webpack-plugin const CleanWebpackPlugin = require('clean-webpack-plugin'); //js壓縮 npm i -D uglifyjs-webpack-plugin const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); //單獨打包css,webpack3是利用extract-text-webpack-plugin外掛提取單獨打包css檔案 //webpack4得使用mini-css-extract-plugin npm i -D mini-css-extract-plugin const MiniCssExtractPlugin = require("mini-css-extract-plugin"); //壓縮css npm i -D optimize-css-assets-webpack-plugin const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); //用於打包後的檔案轉碼 npm i webpack-encoding-plugin const EncodingPlugin = require("webpack-encoding-plugin"); //提取公共模組 請參考https://segmentfault.com/a/1190000012828879 //引入glob正則匹配多頁面 npm i -D glob var glob = require('glob'); //安裝webpack npm i -D [email protected]<version>(版本號) //webpack4後將webpack-cli分別出來要自己安裝 npm in -D webpack-cli const webpack = require('webpack'); //處理檔案路徑的工具 const path = require('path'); //設定變數判斷是開發環境還是生產環境 npm i -D cross-env const devMode = process.env.NODE_ENV !== 'production'; //獲取所有路口js,生成一個路徑物件. var getEntry = function () { var entry = {};   //首先我們先讀取我們的開發目錄   glob.sync('./source/**/*.js').forEach(function (name) {     var n = name.slice(name.lastIndexOf('source/') + 7, name.length - 3);     n = n.slice(0, n.lastIndexOf('/'));     //接著對路徑字串進行了一些裁剪成想要的路徑     entry[n] = name;   });   console.log(entry);   /**     *    entry = {     *               'crowd/index' : './source/main/index/index.js',     *               'index/index' : './source/content/index/index.js'     *           }   *   **/   //最後返回entry 給 webpack的entry   return entry; }; module.exports = {   entry: getEntry(), //入口檔案   output: { //檔案輸出位置   path: path.resolve(__dirname, 'dist'), //配置輸出路徑     filename: "js/[name].bundle.js", //檔案輸出形式     chunkFilename: "js/[name].chunk.js",     publicPath: '/'//虛擬目錄,自動指向path編譯目錄 }, //tips:chunkFilename網上覺得靠譜的解釋 //chunkname是未被列在entry中,卻又需要被打包出來的檔案命名配置。什麼場景需要呢?在按需載入(非同步)模組的時候, //這樣的檔案是沒有被列在entry中的,如使用CommonJS的方式非同步載入模組: // require.ensure(["modules/tips.jsx"], function(require) { // var a = require("modules/tips.jsx"); // // ... // }, 'tips');
//tips:一般來說,引入第三方庫有一下三種情況: // 通過CDN引入; // 通過npm 安裝並引入; // 第三方js檔案就在本地 resolve: {//一些配置項,如第三方的js檔案就在本地,怎麼通過webpack引入   alias: {     $: path.resolve(__dirname, './dist/jquery.js'),     jQuery: path.resolve(__dirname, './dist/jquery.js'),   } }, plugins: [ //外掛     require("autoprefixer"),//引入自動補全字首,直接引入autoprefixer-loader並沒有生效,   //安裝postcss-loader並引入autoprefixer時生效,並建立postcss.config.js檔案   new webpack.HotModuleReplacementPlugin(),//啟動模組熱替換   new webpack.NamedModulesPlugin(), //用於啟動HMR時可以顯示模組的相對路徑   new UglifyJsPlugin({}),//js壓縮   new MiniCssExtractPlugin({//css分離     filename: devMode ? 'css/[name].css' : 'css/[name].[hash:5].css',     chunkFilename: devMode ? 'css/[id].css' : 'css/[id].[hash:5].css',   }),   new OptimizeCSSAssetsPlugin({}),//css壓縮   //多頁應用時配置多個html時,那麼就需要例項化該外掛多次   new HtmlWebpackPlugin({     template: 'src/html/index.html',     excludeChunks: ['list', 'detail']//配置不允許注入的chunk   }),   new HtmlWebpackPlugin({     filename: 'list.html',     template: 'src/html/list.html',     chunks: ['common', 'list']//允許插入到模板中的一些chunk,不配置此項預設會將entry中所有的chunk注入到模板中   }),   new HtmlWebpackPlugin({     filename: 'detail.html',     template: 'src/html/detail.html',     chunks: ['common', 'detail']   }),   //用來專案的轉碼   new EncodingPlugin({     encoding: 'GB2312'   }),   //清除dist資料夾   new CleanWebpackPlugin(['dist']) ], //模組 module: {   rules: [   {     test: /\.js$/,     use: [     {       loader: 'babel-loader',//cnpm i -D babel-loader @babel/core @babel/preset-env webpack       options: {//npm i -S babel-polyfill 實現瀏覽器對不支援API的相容(相容舊環境、填補)       presets: ['@babel/preset-env']     }   } ],   exclude: /node_modules/ }, {   test: /\.(sa|sc|c)ss$/,   use: [//npm i -D style-loader css-loader     devMode ? 'style-loader' : MiniCssExtractPlugin.loader,//因為MiniCssExtractPlugin不支援熱替換,所以當是生產環境時不啟用這個外掛     'css-loader',     'postcss-loader',//npm i -D postcss-loader     // {網上還有這種寫法     // loader: 'postcss-loader',     // options: {       // plugins: () => [       // require('autoprefixer')     // ],   // } // },   'sass-loader',//使用sass-loader要使用node-loader,npm i -D sass-loader node-sass   {   loader: 'px2rem-loader',//配合flexible實現移動端下的適配 npm i px2rem-loader   // options here     options: {       remUni: 75,       remPrecision: 8     }   }   ] }, {   test: /\.(jpg|png|gif|jpeg)$/,   use: [ {//npm i -D url-loader     loader: 'url-loader',// 在檔案大小(單位 byte)低於指定的限制時,可以返回一個 DataURL。     options: {       limit: 10000,//設定位元組限制       name: 'img/[name]_[hash:5].[ext]'     }   } ]  } ] }, //配置開發服務功能 npm i -D webpack-dev-server devServer: {   contentBase: path.resolve(__dirname, 'dist'),   historyApiFallback: true,   hot: true,   port: 9000,   publicPath:'/',   } };