開發必備的webpack4

首先webpack4建議使用node版本在8.5以上,是由於要兼容新版npm下的npx,cmd中node -v查看node版本。css

1.什麼是webpack

WebPack能夠看作是模塊打包機:它作的事情是,分析你的項目結構,找到JavaScript模塊以及其它的一些瀏覽器不能直接運行的拓展語言(Scss,TypeScript等),並將其打包爲合適的格式以供瀏覽器使用。html

構建就是把源代碼轉換成發佈到線上的可執行 JavaScrip、CSS、HTML 代碼,包括以下內容。前端

  • 代碼轉換:TypeScript 編譯成 JavaScript、SCSS 編譯成 CSS 等。
  • 文件優化:壓縮 JavaScript、CSS、HTML 代碼,壓縮合並圖片等。
  • 代碼分割:提取多個頁面的公共代碼、提取首屏不須要執行部分的代碼讓其異步加載。
  • 模塊合併:在採用模塊化的項目裏會有不少個模塊和文件,須要構建功能把模塊分類合併成一個文件。
  • 自動刷新:監聽本地源代碼的變化,自動從新構建、刷新瀏覽器。
  • 代碼校驗:在代碼被提交到倉庫前須要校驗代碼是否符合規範,以及單元測試是否經過。
  • 自動發佈:更新完代碼後,自動構建出線上發佈代碼並傳輸給發佈系統。

構建實際上是工程化、自動化思想在前端開發中的體現,把一系列流程用代碼去實現,讓代碼自動化地執行這一系列複雜的流程。 構建給前端開發注入了更大的活力,解放了咱們的生產力。node

2.初始化項目

  • 初始化package.json
npm init -y 
複製代碼
// package.json 文件中
"scripts": {
    "build": "webpack --profile --progress --colors --display-error-details",
    "dev": "webpack --display-modules --profile --progress --colors --display-error-details"
  },

複製代碼
  • color 輸出結果帶彩色,好比:會用紅色顯示耗時較長的步驟react

  • profile 輸出性能數據,能夠看到每一步的耗時jquery

  • progress 輸出當前編譯的進度,以百分比的形式呈現webpack

  • display-modules 默認狀況下 node_modules 下的模塊會被隱藏,加上這個參數能夠顯示這些被隱藏的模塊git

  • display-error-details 輸出詳細的錯誤信息github

  • 全局安裝web

npm install webpack -g
複製代碼
  • 本地安裝
npm install webpack webpack-cli -D//-D是指開發環境須要,上線不須要,下同;
複製代碼

通常推薦本地安裝,安裝在本身的項目中,否則版本不一樣會有不兼容。

3. 快速上手

3.1 webpack核心概念

  • Entry:入口,Webpack 執行構建的第一步將從 Entry 開始,可抽象成輸入。
  • Module:模塊,在 Webpack 裏一切皆模塊,一個模塊對應着一個文件。Webpack 會從配置的 Entry 開始遞歸找出全部依賴的模塊。
  • Chunk:代碼塊,一個 Chunk 由多個模塊組合而成,用於代碼合併與分割。
  • Loader:模塊轉換器,用於把模塊原內容按照需求轉換成新內容。
  • Plugin:擴展插件,在 Webpack 構建流程中的特定時機注入擴展邏輯來改變構建結果或作你想要的事情。
  • Output:輸出結果,在 Webpack 通過一系列處理並得出最終想要的代碼後輸出結果。

3.2 配置webpack

npm install webpack webpack-cli -D
複製代碼
  • 建立src
  • 建立dist
    • 建立index.html
  • 配置文件webpack.config.js
    • entry:配置入口文件的地址
    • output:配置出口文件的地址
    • module:配置模塊,主要用來配置不一樣文件的加載器
    • plugins:配置插件
    • devServer:配置開發服務器
// 基於node的 遵循commonjs規範的
let path = require('path');//node的模塊
module.exports = {
  entry:'./src/index.js', // 入口
  output:{
    filename:'build.js',
    // 這個路徑必須是絕對路徑
    path: path.resolve('./dist')
  }, // 出口
  devServer:{
    contentBase:'./dist',
    port:8080,
    compress:true,// 服務器壓縮
    open:true,// 自動打開瀏覽器
    // hot:true//熱更新
  },// 開發服務器
  module:{}, // 模塊配置
  plugins:[], // 插件的配置
  mode:'development', // 能夠更改模式
  resolve:{}, // 配置解析
}
// 在webpack中如何配置開發服務器 webpack-dev-server
複製代碼

4. 配置開發服務器

npm i webpack-dev-server –D
複製代碼
  • contentBase 配置開發服務運行時的文件根目錄
  • host:開發服務器監聽的主機地址
  • compress 開發服務器是否啓動gzip等壓縮
  • port:開發服務器監聽的端口
+ devServer:{
+        contentBase:path.resolve(__dirname,'dist'),
+        host:'localhost',
+        compress:true,
+        port:8080
+ }//開發服務器
複製代碼
+  "scripts": {
+    "build": "webpack --mode development",
+    "dev": "webpack-dev-server --open --mode development "
+  }//開啓本地服務 npm run dev
複製代碼

5. 入口文件的類型

5.1單入口+單出口

這種狀況不多,通常就以字符串的形式出現便可,例如:

entry: './src/index.js',
複製代碼

5.2 多入口數組形式+單出口

entry:['./src/index.js','./src/a.js']
複製代碼

5.1. 多入口+多出口

有時候咱們的頁面能夠不止一個HTML頁面,會有多個頁面,因此就須要多入口

entry: {
        index: './src/index.js',
        main:'./src/main.js'
    },
     output: {
            path: path.resolve(__dirname, 'dist'),
            filename: '[name].[hash].js',
            publicPath:PUBLIC_PATH
        },
        new HtmlWebpackPlugin({
                    minify: {
                        removeAttributeQuotes:true
                    },
                    hash: true,
                    template: './src/index.html',
                    chunks:['index'],
                    filename:'index.html'
                }),
                new HtmlWebpackPlugin({
                    minify: {
                        removeAttributeQuotes:true
                    },
                    hash: true,
                    chunks:['main'],
                    template: './src/main.html',
                    filename:'main.html'
                })],
複製代碼

6. 支持加載css文件

6.1 什麼是Loader

經過使用不一樣的Loader,Webpack能夠要把不一樣的文件都轉成JS文件,好比CSS、ES6/七、JSX等

  • test:匹配處理文件的擴展名的正則表達式
  • use:loader名稱,就是你要使用模塊的名稱
  • include/exclude:手動指定必須處理的文件夾或屏蔽不須要處理的文件夾
  • query:爲loaders提供額外的設置選項

loader三種寫法

  • use
  • loader
  • use+loader

6.2 css-loader

npm i style-loader css-loader -D
複製代碼

配置加載器

module: {
+        rules:[
+            {
+                test:/\.css$/,
+                use:['style-loader','css-loader'],//從右往左寫,webpack特性
+                include:path.join(__dirname,'./src'),
+                exclude:/node_modules/
+            }
+        ]
    },
複製代碼

7. 支持圖片

7.1 手動添加圖片

npm i file-loader url-loader -D
複製代碼
  • file-loader 解決CSS等文件中的引入圖片路徑問題
  • url-loader 當圖片較小的時候會把圖片BASE64編碼,大於limit參數的時候仍是使用file-loader 進行拷貝
let logo=require('./images/logo.png');
let img=new Image();
img.src=logo;
document.body.appendChild(img);
複製代碼
{
    test:/\.(jpg|png|gif|svg)$/,
    use:'url-loader',
    include:path.join(__dirname,'./src'),
    exclude:/node_modules/
  }
複製代碼

7.2 在CSS中引入圖片

還能夠在CSS文件中引入圖片

.img-bg{
    background: url(./images/logo.png);
    width:173px;
    height:66px;
}
複製代碼

8. 自動產出html

8.1 什麼是插件

插件是 wepback 的支柱功能。webpack 自身也是構建於,你在 webpack 配置中用到的相同的插件系統之上!

  • 插件使用
npm install 插件名 -D
複製代碼

由於插件都是類,引用方式,在plugins數組中 new 插件名 便可使用。

8.2 咱們但願自動能產出HTML文件,並在裏面引入產出後的資源

npm i html-webpack-plugin -D
複製代碼
  • minify 是對html文件進行壓縮,removeAttrubuteQuotes是去掉屬性的雙引號
  • hash 引入產出資源的時候加上哈希避免緩存
  • template 模版路徑
plugins: [
+        new HtmlWebpackPlugin({
+       minify: {
+            removeAttributeQuotes:true
+        },
+        hash: true,
+        template: './src/index.html',
+        filename:'index.html'
    })]
複製代碼

9. 分離CSS

由於CSS的下載和JS能夠並行,當一個HTML文件很大的時候,咱們能夠把CSS單獨提取出來加載,webpack4中mini-css-extract-plugin也能夠實現,可是目前bug比較多,不能分紅多個css。

npm install --save-dev extract-text-webpack-plugin@next
複製代碼
{
    test:/\.css$/,
    use: ExtractTextWebpackPlugin.extract({
        use:'css-loader'
    }),
    include:path.join(__dirname,'./src'),
    exclude:/node_modules/
},

plugins: [
    new ExtractTextWebpackPlugin('css/index.css'),
]
複製代碼

處理圖片路徑問題

const PUBLIC_PATH='/';

output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath:PUBLIC_PATH
},
複製代碼

指定打包後的圖片位置

use: [
    {
     loader: 'url-loader',
     options: {
       limit: 1024,
      outputPath:'images/'
     }
    }
],
複製代碼

在HTML中使用圖片

npm i html-withimg-loader -D
複製代碼
<div class="img-container "><img src="./images/logo.png" alt="logo.png"></div>
複製代碼
{
+    test:/\.(html|html)$/,
+    use:'html-withimg-loader',
+    include:path.join(__dirname,'./src'),
+    exclude:/node_modules/
  }
複製代碼

10. 編譯less 和 sass

npm i less less-loader -D
npm i node-saas sass-loader -D
複製代碼
@color:orange;
.less-container{
	border:1px solid @color;
}

$color:green;
.sass-container{
	border:1px solid $color;
}
複製代碼
const cssExtract=new ExtractTextWebpackPlugin('css.css');
const lessExtract=new ExtractTextWebpackPlugin('less.css');
const sassExtract=new ExtractTextWebpackPlugin('sass.css');

 {
                test:/\.less$/,
                use: lessExtract.extract({
                    use:['css-loader','less-loader']
                }),
                include:path.join(__dirname,'./src'),
                exclude:/node_modules/
            },
            {
                test:/\.scss$/,
                use: sassExtract.extract({
                    use:['css-loader','sass-loader']
                }),
                include:path.join(__dirname,'./src'),
                exclude:/node_modules/
            },
複製代碼

11. 處理CSS3屬性前綴

爲了瀏覽器的兼容性,有時候咱們必須加入-webkit,-ms,-o,-moz這些前綴

  • Trident內核:主要表明爲IE瀏覽器, 前綴爲-ms
  • Gecko內核:主要表明爲Firefox, 前綴爲-moz
  • Presto內核:主要表明爲Opera, 前綴爲-o
  • Webkit內核:產要表明爲Chrome和Safari, 前綴爲-webkit
npm i postcss-loader autoprefixer -D
複製代碼

postcss-loader

postcss.config.js

module.exports={
	plugins:[require('autoprefixer')]
}
複製代碼
.circle {
+    transform: translateX(100px);
複製代碼
{
                test:/\.css$/,
                use: cssExtract.extract({
+                   use:['css-loader','postcss-loader']
                }),
                include:path.join(__dirname,'./src'),
                exclude:/node_modules/
            },
複製代碼

12. 轉義ES6/ES7/JSX

Babel實際上是一個編譯JavaScript的平臺,能夠把ES6/ES7,React的JSX轉義爲ES5

npm i babel-core babel-loader babel-preset-env babel-preset-stage-0 babel-preset-react -D
複製代碼
{
        test:/\.jsx?$/,
        use: {
            loader: 'babel-loader',
            options: {
                presets: ["env","stage-0","react"]
            }
        },
        include:path.join(__dirname,'./src'),
        exclude:/node_modules/
        },
複製代碼

13. 如何調試打包後的代碼

webapck經過配置能夠自動給咱們source maps文件,map文件是一種對應編譯文件和源文件的方法

  • source-map 把映射文件生成到單獨的文件,最完整最慢
  • cheap-module-source-map 在一個單獨的文件中產生一個不帶列映射的Map
  • eval-source-map 使用eval打包源文件模塊,在同一個文件中生成完整sourcemap
  • cheap-module-eval-source-map sourcemap和打包後的JS同行顯示,沒有映射列
devtool:'eval-source-map'
複製代碼

14. 拷貝靜態文件

有時項目中沒有引用的文件也須要打包到目標目錄

npm i copy-webpack-plugin -D
複製代碼
new CopyWebpackPlugin([{
            from: path.join(__dirname,'public'),//靜態資源目錄源地址
            to:'./public' //目標地址,相對於output的path目錄
        }]),
複製代碼

15. 打包前先清空輸出目錄

npm i  clean-webpack-plugin -D
複製代碼
new cleanWebpaclPlugin(path.join(__dirname,'dist'))
複製代碼

16. 壓縮CSS

webpack能夠消除未使用的CSS

npm i -D purifycss-webpack purify-css glob
複製代碼
new PurifyCSSPlugin({//purifycss根據這個路徑配置遍歷你的HTML文件,查找你使用的CSS
  paths:require('glob').sync(path.join(__dirname,'src/*.html'))
}),
複製代碼

17. resolve解析

17.1 extensions

指定extension以後能夠不用在require或是import的時候加文件擴展名,會依次嘗試添加擴展名進行匹配

resolve: {
    //自動補全後綴,注意第一個必須是空字符串,後綴必定以點開頭
   extensions: [" ",".js",".css",".json"],
},
複製代碼

17.2 alias

配置別名能夠加快webpack查找模塊的速度

  • 每當引入jquery模塊的時候,它會直接引入jqueryPath,而不須要從node_modules文件夾中按模塊的查找規則查找
  • 不須要webpack去解析jquery.js文件
const bootstrap=path.join(__dirname,'node_modules/bootstrap/dist/css/bootstrap.css')
resolve: {
 +       alias: {
 +           'bootstrap': bootstrap
 +       }
    },
複製代碼

18. 區分環境變量

許多 library 將經過與 process.env.NODE_ENV 環境變量關聯,以決定 library 中應該引用哪些內容。例如,當不處於生產環境中時,某些 library 爲了使調試變得容易,可能會添加額外的日誌記錄(log)和測試(test)。其實,當使用 process.env.NODE_ENV === 'production' 時,一些 library 可能針對具體用戶的環境進行代碼優化,從而刪除或添加一些重要代碼。咱們可使用 webpack 內置的 DefinePlugin 爲全部的依賴定義這個變量:

npm install cross-env -D
複製代碼
"scripts": {
    "build": "cross-env NODE_ENV=production webpack --mode development",
     "dev": "webpack-dev-server --open --mode development "
  },
複製代碼
plugins: [
    new webpack.DefinePlugin({
        NODE_ENV:JSON.stringify(process.env.NODE_ENV)
}),
複製代碼
if (process.env.NODE_ENV == 'development') {
	console.log('這是開發環境');
} else {
	console.log('這是生產環境');
}
複製代碼

19. 抽離公共部分

optimization:{
    splitChunks:{
        cacheGroups:{
            vendor:{//抽離第三插件
                test:/node_module/,
                chunks:'initial',
                name: 'vendor',
                priority:10,//優先級
            },
            commons:{//抽離公共的js
                chunks:'initial',
                name:'commons',
                minSize: 0//只要超出0字節就生成新的公共的包
            }
        }
    }
},
複製代碼
  • 從右往左,首先抽離公共部分js(好比兩個文件共用的部分)會把第三方(好比jquery)首先打包,此時須要設置優先級priority,第三方插件不會打包到公共部分。

謝謝你看到了最後

相關文章
相關標籤/搜索