webpack4.29.6搭建常用功能的環境

超喜歡水果果果果果發表於2019-04-01

因專案需要,用webpack搭建一個常用功能的環境。
初步功能羅列如下:
自動配置多入口出口
less轉css
css字首自動補齊
css提取成單獨檔案
css壓縮
圖片壓縮
引入字型和svg js Babel 壓縮
css和js的分離/合併和過濾

1.建立並且進入資料夾

mkdir webpack4.29.6 && cd webpack4.29.6
複製程式碼

2.如下圖建立各個demo檔案和圖片

webpack4.29.6搭建常用功能的環境

index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>test</title>
</head>
<body>
   隨便寫一些index2333
</body>
</html>
複製程式碼
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>test</title>
</head>
<body>
   隨便寫一些about2333
</body>
</html>
複製程式碼

其他的檔案可以先空著,圖片先不匯入也沒關係。

3建立package.json(以下所有命令都是在webpack4.29.6資料夾下執行)

npm init -y
複製程式碼

4.安裝以下幾個依賴

(
webpack/webpack-cli這兩個需要注意,3.x以前版本是合併在一起的,4.x後拆分了 webpack-dev-server:起服務
html-webpack-plugin:動態生成html
webpack-merge:合併webpack配置檔案
)

npm install -D webpack webpack-cli webpack-dev-server html-webpack-plugin webpack-merge
複製程式碼

確保區域性依賴和全域性依賴版本都如下圖是最新的(看清楚了,webpack是4.29.6的,如果你因為網路問題裝成3.幾的,後面將全部報錯。這步很關鍵,不然你會有無窮盡的麻煩,如果實在不成功可以先把全域性node下的webpack相關檔案刪除,window在c盤/Program Files/nodejs/下)。

webpack4.29.6搭建常用功能的環境

5.建立三個webpack配置文字(1.common2.dev3.prod)並且分別寫入

touch webpack.common.js webpack.dev.js webpack.prod.js
複製程式碼

webpack.common.js:

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: {
    index: "./src/js/index.js"
  },
  output: {
    //[name] 輸出名稱等於輸入名稱   [contenthash:8] 八位hash
    filename: "[name].[contenthash:8].js",  
    //你應該知道的node path 知識: http://nodejs.cn/api/path.html
    path: path.resolve(__dirname, "dist")
  },
  module: {
    rules: [
    
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: "index.html",
      template: "./src/index.html"
    })
  ]
};

複製程式碼

webpack.dev.js:

const merge = require("webpack-merge");
const common = require("./webpack.common.js");

module.exports = merge(common, {
  mode: "development",
  //開啟除錯
  devtool: "source-map",
  devServer: {
    //設定基本目錄結構
    contentBase: "./dist",
    //伺服器的IP地址,可以使用IP也可以使用localhost
    host: "localhost",
    //服務端壓縮是否開啟
    compress: true,
    //配置服務埠號
    port: 8090
  }
});

複製程式碼

webpack.prod.js:

const merge = require("webpack-merge");
const common = require("./webpack.common.js");

module.exports = merge(common, {
  mode: "production",
});

複製程式碼

6.修改下package.json中的script物件

  "scripts": {
    "dev": "webpack-dev-server --config webpack.dev.js",
    "build": "rimraf dist && webpack --config webpack.prod.js"
  },
複製程式碼

7.嘗試啟動服務或者打包

啟動服務:

npm run dev
複製程式碼

打包: (rimraf dist: 打包前刪除了rimraf資料夾再重新生成)

npm run build
複製程式碼

dist:

webpack4.29.6搭建常用功能的環境
這樣便成功了第一步。

因為修改了配置檔案每步都要重啟服務比較麻煩,我們這裡引入nodemon。並且新增一條命令

npm install -D nodemon
複製程式碼

// 監聽webpack.common.js檔案,有變動的話就重新啟動 npm run dev

"startdev": "nodemon --watch webpack.common.js --exec  npm run dev "
複製程式碼

package.json:

webpack4.29.6搭建常用功能的環境

開始正式配置專案常見的功能

前面打包的檔案圖片可以看到只打出了index.html,這裡看看怎麼引入多個html

webpack.common.js: 在入口增加多一個about.js和外掛多生產一個例項即可:

webpack4.29.6搭建常用功能的環境
但是手動新增有點搓,嘗試用node遍歷自動匯入:
在根目錄新建一個multi.page.js檔案:

multi.page.js:

// 多入口出口處理
const path = require("path");
const fs = require("fs");
const htmlWebpackPlugin = require("html-webpack-plugin");
const pagesPath = path.resolve("./src");

var pageList = [];
function readPages() {
  fs.readdirSync(pagesPath).forEach(e => {
    var fullPath = pagesPath + "/" + e;
    if (e.includes("html")) {
      var baseName = e.slice(0, e.indexOf("."));
      pageList.push({
        entry: pagesPath + "\\js\\" + baseName + ".js",
        chunkName: baseName,
        template: pagesPath +'\\'+ e
      });
    }
  });
  return pageList;
}

// 入口
exports.getEntryPages = function() {
  return readPages().reduce((r, page) => {
    r[page.chunkName] = page.entry;
    return r;
  }, {});
};
//出口
exports.htmlPlugins = function() {
  var list = readPages().map(page => {
    var options = {
      filename: page.chunkName + ".html",
      template: page.template,
      chunks: [page.chunkName]
    };
    return new htmlWebpackPlugin(options);
  });
  return list;
};

複製程式碼

webpack.common.js:

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const multiPage = require("./multi.page");

module.exports = {
  //   entry: {
  //     index: "./src/js/index.js",
  //     about: "./src/js/about.js"
  //   },
  entry: multiPage.getEntryPages(),
  output: {
    //[name] 輸出名稱等於輸入名稱   [contenthash:8] 八位hash
    filename: "[name].[contenthash:8].js",
    //你應該知道的node path 知識: http://nodejs.cn/api/path.html
    path: path.resolve(__dirname, "dist")
  },
  module: {
    rules: []
  },
  plugins: [
    // new HtmlWebpackPlugin({
    //   filename: "index.html",
    //   template: "./src/index.html"
    // }),
    // new HtmlWebpackPlugin({
    //   filename: "about.html",
    //   template: "./src/about.html"
    // })
    ...multiPage.htmlPlugins()
  ]
};

複製程式碼

就是將手動引入匯出改善成nodejs自動遍歷

後面就是常見功能了,先暫時寫到webpack.common.js裡面方便除錯,最後按需切到webpack.dev.js或者webpack.prod.js

處理css(這裡我以less為例)安裝以下依賴

npm install -D css-loader style-loader less less-loader 
複製程式碼

修改webpack.common.js:

  module: {
    rules: [
      {
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
        include: path.resolve(__dirname, "./src") // 制定路徑提升效能
      }
    ]
  },
複製程式碼

修改index.js引入index.less,並且隨意寫點樣式

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>test</title>
</head>
<body>
    <div class="test">
        隨便寫點什麼 這裡不要自己引入css和js 全部交給webpack來處理
    </div>
</body>
</html>
複製程式碼

index.js:

import index from "../css/index.less";
複製程式碼

index.less

body {
  display: flex;
  background: #666;
  .test {
    color: #ff0;
  }
}
複製程式碼

就會發現相關樣式在head style 裡了
再優化一步,將style提出來
安裝依賴mini-css-extract-plugin

npm install -D mini-css-extract-plugin
複製程式碼

webpack.common.js 引進依賴、修改規則和產出,檔案總體如下

webpack.common.js:

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const multiPage = require("./multi.page");
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); //提取css檔案

module.exports = {
  //   entry: {
  //     index: "./src/js/index.js",
  //     about: "./src/js/about.js"
  //   },
  entry: multiPage.getEntryPages(),
  output: {
    //[name] 輸出名稱等於輸入名稱   [contenthash:8] 八位hash
    filename: "[name].[contenthash:8].js",
    //你應該知道的node path 知識: http://nodejs.cn/api/path.html
    path: path.resolve(__dirname, "dist")
  },
  module: {
    rules: [
      {
        test: /\.less$/,
        // use: ["style-loader", "css-loader", "less-loader"],
        use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
        include: path.resolve(__dirname, "./src") // 制定路徑提升效能
      }
    ]
  },
  plugins: [
    // new HtmlWebpackPlugin({
    //   filename: "index.html",
    //   template: "./src/index.html"
    // }),
    // new HtmlWebpackPlugin({
    //   filename: "about.html",
    //   template: "./src/about.html"
    // })
    ...multiPage.htmlPlugins(),
    new MiniCssExtractPlugin({
      filename: "css/[name].[contenthash:8].css"
    })
  ]
};

複製程式碼

繼續優化將css字首自動補齊

安裝依賴:

npm install -D postcss-loader autoprefixer
複製程式碼

修改package.json:

  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ]
複製程式碼

修改webpack.common.js:

--- use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
+++  use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              plugins: () => [require("autoprefixer")()]
            }
          },
          "less-loader"
        ],
複製程式碼

最後壓縮css檔案

安裝依賴:

npm install -D optimize-css-assets-webpack-plugin
複製程式碼

修改webpack.common.js:

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


new OptimizeCssAssetsPlugin({
    assetNameRegExp: /\.css$/g, 
    cssProcessor: require('cssnano'), //用於優化\最小化CSS的CSS處理器,預設為cssnano
    cssProcessorOptions: { safe: true, discardComments: { removeAll: true } }, //傳遞給cssProcessor的選項,預設為{}
    canPrint: true                    //一個布林值,指示外掛是否可以將訊息列印到控制檯,預設為true
}),
複製程式碼

檢視一下結果 原始檔:

webpack4.29.6搭建常用功能的環境
打包後的:

webpack4.29.6搭建常用功能的環境
另外補充一句,看到頭部這裡莫名其妙引入了一個這個style和相關樣式,一臉懵逼還未找到問題所在。
webpack4.29.6搭建常用功能的環境

引入圖片以及對圖片進行壓縮

npm install -D css-loader file-loader html-withimg-loader image-webpack-loader
複製程式碼

webpack.common.js:

{
        test: /\.(svg|png|jpe?g|gif)$/i,
        use: [
          {
            loader: "url-loader",
            options: {
              limit: 1,
              name: "images/[name].[contenthash:8].[ext]",
              publicPath: "../"
            }
          },
           {
            loader: "image-webpack-loader",
            options: {
              pngquant: {
                quality: "70-80",
                speed: 1
              }
            }
          }
        ]
      },
      {
        test: /\.html$/,
        use:[
            'html-withimg-loader'
        ]
      }
複製程式碼

引入字型

修改webpack.common.js:

      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: [
          {
            loader: "file-loader",
            options: {
              name: "assets/[name].[contenthash:8].[ext]",
              publicPath: "../"
            }
          }
        ]
      }

複製程式碼

babel 升級後有點小噁心..不想說了 後面再根據專案豐富css和js的提取和合並過濾

from:webpack.docschina.org/api/