webpack4x,走你...

火雲邪神發表於2018-04-10

webpack已經是前端開發必不可少的神器了;

一、#先看看他的核心功能,為什麼用他?#

1.打包:可以把多個Javascript檔案打包成一個檔案,減少伺服器壓力和下載頻寬。

2.轉換:把擴充語言轉換成為普通的JavaScript,讓瀏覽器順利執行。

3.優化:前端變的越來越複雜後,效能也會遇到問題,而WebPack也開始肩負起了優化和提升效能的責任。

4.Webpack在生產環境中有一個重要的作用就是減少http的請求數

以上三點即是它=他的核心作用。

webpack4x,走你...

二、webpack(當下最新版4.8.3)安裝及環境配置

webpack這傢伙更新甚快,所以不同版本的webpack所使用的命令也幾乎各不相同

1.全域性安裝webpack npm i webpack -g

2.進入專案資料夾,初始化專案,為了生成pake.json檔案;npm init 持續回車即可

3.安裝webpack的依賴node_modules; npm i -D webpack

4.全域性安裝webpack-cli;npm i webpack-cli -g

5.設定預設開發環境,設定mode(模式),指定是“開發環境(production)”還是“生產環境(development)”; 當然在持續開發中,得優先設定開發環境;webpack --mode development;

6.以後打包即可輸入webpack --mode development;但是明顯每次這樣輸入繁瑣至極; 在pake.json文中的script下配置 "dev":"webpack --mode development" 和 "build":"webpack --mode production";

輸入npm run dev即可打包到專案自動生成的dist資料夾中;npm run build打包生產環境;

7.所有的開發檔案必須在src資料夾下,因為webpack4預設的入口資料夾就是src;

注意:

1、webpack-cli必須要全域性安裝,否則不能使用webpack指令;

2、webpack也必須要全域性安裝,否則也不能使用webpack指令。

3、webpack4.x中webpack.config.js這樣的配置檔案不是必須的。

4、預設入口檔案是./src/index.js,預設輸出檔案./dist/main.js。

三、配置webpack.config.js| webpack-cli init

Will your application have multiple bundles? No // 單入口 string, 多頁面 object
2. Which module will be the first to enter the application? [example: './src/index'] ./src/index // 程式入口
3. What is the location of "app"? [example: "./src/app"] './src/index' // 程式主檔案
4. Which folder will your generated bundles be in? [default: dist]: // 輸出目錄,預設 dist
5. Are you going to use this in production? No // (Yes 第9步預設'config', No 則為 'prod')
6. Will you be using ES2015? Yes // 會新增 ES6 => ES5 的配置
7. Will you use one of the below CSS solutions? CSS // 選一種樣式語言,會生成對應的 loader 配置
8. If you want to bundle your CSS files, what will you name the bundle? (press enter to skip) // 回車跳過
9. Name your 'webpack.[name].js?' [default: 'config']: // webpack.config.js

Congratulations! Your new webpack configuration file has been created!

複製程式碼

webpack.config.js一覽


// 從依賴中引入path
const path = require('path');
const uglify = require('uglifyjs-webpack-plugin');//JS壓縮外掛,簡稱uglify
const htmlPlugin= require('html-webpack-plugin');//html打包
// const extractTextPlugin = require('exrract-text-plugin');//extract-text-webpack-plugin將CSS檔案分離出來
// __dirname是node.js的全域性變數,它指向當前執行指令碼所在的目錄。
var website = {
  publicPath:"http://localhost:5252/"
}
module.exports = {
    devtool: 'eval-source-map',
    // entry:__dirname + '/src/main.js',
    entry:{
       main:'./src/main.js'
    },
    output:{
      //打包的路徑資料夾
      path:path.resolve(__dirname,'dist'),//__dirname 表示當前檔案所在的目錄的絕對路徑,path.resolve()方法將一系列路徑或路徑段解析為絕對路徑
      //或者這樣寫
      // filename:'[name].js'//filename:是打包後的檔名稱
      // filename:'[name].[chunkHash:2].js'//每次打包都會引入最新的.js,防止瀏覽器快取
    },
    //模組:例如解讀CSS,圖片如何轉換,壓縮
    module:{
      rules: [
        {
          test: /\.css$/,
          use: ['style-loader', 'css-loader'] 
          //或者loader: [ 'style-loader', 'css-loader' ]
          //或者:use:[
            // {loader:'style-loader'},
            // {loader:'css-loader'}
          // ]
          
        },
        {
          test:/\.(png|jpg|gif)/,
          use:[{
              loader:'url-loader',
              options:{
                  limit:500000
              }
          }]
       }
      ]
    },
    //外掛,用於生產模版和各項功能
    plugins:[
      new uglify(),
      new htmlPlugin({
        minify:{
            removeAttributeQuotes:true
        },
        hash:true,
        template:'./src/index.html'
       
    })
    // new extractTextPlugin("./css/index.css")//配置分離後的路勁
    ],
    mode:'development',
    //配置webpack開發服務功能
    devServer: {
      //設定基本目錄結構
      contentBase: "./dist",//本地伺服器所載入的頁面所在的目錄 || contentBase:path:path.resolve(__dirname,'dist')
      //伺服器的IP地址,可以使用IP也可以使用localhost
      host:'localhost',
      //服務端壓縮是否開啟
      compress:true,
      //配置服務埠號
      port:5252,
      historyApiFallback: true,//不跳轉
      inline: true//實時重新整理
    } 
  }
  
複製程式碼

三、webpack:服務和熱更新

安裝服務npm install webpack-dev-server –save-dev 並在page.json中 設定 scripts": { "server":"webpack-dev-server" },

熱更新:webpack-dev-server 提供了兩種模式用於自動重新整理頁面: npm run server; npm start使用此命令在pake.json中scrpts中設定: "start": "webpack && webpack-dev-server --hot --inline"

三、loaders(webpack的核心):

所有的Loaders都需要在npm中單獨進行安裝,並在webpack.config.js裡進行配置

1.Loaders的配置型:

test:用於匹配處理檔案的副檔名的表示式,這個選項是必須進行配置的;

use:loader名稱,就是你要使用模組的名稱,這個選項也必須進行配置,否則報錯

include/exclude:手動新增必須處理的檔案(資料夾)或遮蔽不需要處理的檔案(資料夾)(可選);

query:為loaders提供額外的設定選項(可選)。

四、檔案壓縮打包 1.css檔案壓縮,可以在入口檔案index.js中匯入,將其壓縮到dist下的js檔案中;

index.js 寫入 import css from '.././css/index.css'

2.css中的圖片路勁問題:

很顯然,打包後的圖片是404; 所以解決方法是要安裝url-loader 和 file-loader;

npm install --save-dev file-loader url-loader


file-loader:解決引用路徑的問題,拿background樣式用url引入背景圖來說,我們都知道,webpack最終會將各個模組打包成一個檔案,因此我們樣式中的url路徑是相對入口html頁面的,而不是相對於原始css檔案所在的路徑的。這就會導致圖片引入失敗。這個問題是用file-loader解決的,file-loader可以解析專案中的url引入(不僅限於css),根據我們的配置,將圖片拷貝到相應的路徑,再根據我們的配置,修改打包後檔案引用路徑,使之指向正確的檔案。

url-loader:如果圖片較多,會發很多http請求,會降低頁面效能。這個問題可以通過url-loader解決。url-loader會將引入的圖片編碼,生成dataURl。相當於把圖片資料翻譯成一串字元。再把這串字元打包到檔案中,最終只需要引入這個檔案就能訪問圖片了。當然,如果圖片較大,編碼會消耗效能。因此url-loader提供了一個limit引數,小於limit位元組的檔案會被轉為DataURl,大於limit的還會使用file-loader進行copy。


url-loader封裝了file-loader。url-loader不依賴於file-loader,即使用url-loader時,只需要安裝url-loader即可,不需要安裝file-loader,因為url-loader內建了file-loader。

3.css檔案分離

安裝extractTextPlugin; npm install extract-text-webpack-plugin@next --save-dev;

const extractTextPlugin = require("extract-text-webpack-plugin");

**注意:**最新版的webpack要安裝對應升級版的分離外掛,所以要加上@next;

安裝完在webpack.config.js中引入::const extractTextPlugin = require('extract-text-webpack-plugin');

安裝完之後,還得在webpack.config.js中設定載入項:

// use: [
        //   { loader: 'style-loader', options: { sourceMap: true } },
        //   { loader: 'css-loader' }
        // ]
        // css分離:
        替換上面的如下:::
        use: extractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader"
        })
複製程式碼

設定Plugins: new extractTextPlugin('/css/index.css')設定打包後的檔案路勁

npm run dev後可以看見dist資料夾下自動生成css;

4.css檔案分離後,會導致css中的背景圖片路勁不對;

解決方式是: 在webpack.conifg.js中全域性宣告一個ip屬性:

var website ={
  publicPath:"http://localhost:5200/"//你的本機ip地址,或自定義的server埠
}

然後再output(輸出物件)中,呼叫全域性變數設定的屬性publicPath;實際是改其相對路徑為絕對路勁
publicPath:website.publicPath
在進行打包即可找對路勁
複製程式碼

5.處理html中的圖片:路勁及檔案打包

安裝到生產環境中:
npm install html-withimg-loader --save
在webpack.config.js中配置loader:
{
    test: /\.(htm|html)$/i,
     use:[ 'html-withimg-loader'] 
}
然後進行打包,可以發現圖片路勁正確,並被打包
複製程式碼

6.less檔案打包::: 安裝less和less-loader npm i less less-loader -D

首先:在src目錄下新建less檔案;
次之,在入口檔案js中引入less檔案;
import less from '.././less/index.less';

然後再webpack.config.js中配置less-loader:
use: [
            {loader:'css-loader'},
            {loader:'less-loader'} //在js中分離less檔案到css中;
          ]

複製程式碼

7.jslabel轉換::: cnpm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react

在webpack.config.js 中配置bable
{
    test:/\.(jsx|js)$/,
    use:{
        loader:'babel-loader',
        options:{
            presets:[
                "es2015","react"
            ]
        }
    },
    exclude:/node_modules/
}
複製程式碼

現在網路上已經不流行babel-preset-es2015,現在官方推薦使用的是babel-preset-env,

npm install --save-dev babel-preset-env

新建.babelrc檔案,在裡面的配置即可

{
    "presets":["react","env"]
}
複製程式碼

基本的最終webpack.config.js配置

// 在webpack.config.js裡引入必須使用require,否則會報錯的;
const webpack = require('webpack');//引入webpack自帶的外掛包,在plugins中呼叫即可
const path = require('path');//引入node的path模組(node的path 模組提供了一些用於處理檔案路徑的小工具)
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');//此乃壓縮JS的外掛,簡稱uglify
const HtmlWebpackPlugin = require('html-webpack-plugin');//此乃壓縮html的外掛
const extractTextPlugin = require('extract-text-webpack-plugin');//之前將css檔案打包到了js檔案中,沒有將其分離出來,所以用此外掛可以單獨提取css和less
const glob = require('glob');//引入Node.js 中的全域性物件是 global;node的glob模組允許你使用*等符號,來寫一個glob規則;https://blog.csdn.net/tangxiaolang101/article/details/53931145
const PurifyCSSPlugin = require('purifycss-webpack');//PurifyCSS外掛可以大大減少CSS冗餘
// const entry = require(./webpack_config/entry_webpack.js);
// 處理css檔案圖片路勁問題
var website ={
  publicPath:"http://localhost:5200/"
}
// if(process.env.type== "build"){
//   var website={  
//       publicPath:"http://localhost:5200/"
//   }
// }else{
//   var website={
//       publicPath:"http://localhost:5200/"
//   }
// }
// console.log( encodeURIComponent(process.env.type));
module.exports = {
  devtool: 'eval-source-map',
  entry: {
    main:'./src/js/index.js'
  },
  // entry:entry.path,
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist'),
    publicPath:website.publicPath// 處理css檔案圖片路勁問題 呼叫全域性變數設定的屬性publicPath;實際是改其相對路徑為絕對路勁
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          presets: ['env']
        }
      },
      {
        test: /\.css$/,
        // use: [
        //   { loader: 'style-loader', options: { sourceMap: true } },
        //   { loader: 'css-loader' }
        // ]
        // css分離:
        use: extractTextPlugin.extract({
          use: [
            {loader:'css-loader'},
            {loader:'less-loader'}
          ],
          fallback: "style-loader",
        })
      },
      {
        test:/\.(png|jpg|gif)/ ,
        use:[{
            loader:'url-loader',
            options:{
                limit:5000,
                outputPath:'img/'//outputPath屬性表示輸出打包後的檔案路勁 
            }
        }]
     },
    //  配置解決html中的 img標籤圖片路勁404問題
     {
      test: /\.(htm|html)$/i,
       use:[ 'html-withimg-loader'] 
  },
  {
    test: /\.less$/,
  use: [
    {loader: 'style-loader'},
    {loader:'css-loader'},
    {loader:'less-loader'}
  ]
  },
  {
    test:/\.(jsx|js)$/,
    use:{
        loader:'babel-loader',
        options:{
            presets:[
                "es2015","react"
            ]
        }
    },
    exclude:/node_modules/
},
{   
    test:/\.(jsx|js)$/,
    use:{
        loader:'babel-loader',
    },
    exclude:/node_modules/
}
  //  {
  //   watchOptions:{ 
  //     //檢測修改的時間,以毫秒為單位
  //     poll:1000, 
  //     //防止重複儲存而發生重複編譯錯誤。這裡設定的500是半秒內重複儲存,不進行打包操作
  //     aggregateTimeout:500, 
  //     //不監聽的目錄
  //     ignored:/node_modules/, 
  // }
  //  }
    ]
  },
  plugins: [
    new UglifyJSPlugin(),
    new extractTextPlugin('/css/index.css'),
    new HtmlWebpackPlugin({
        minify:{
            removeAttributeQuotes:true  
        },
        hash:true,
        template:'./src/html/index.html',
        filename:'html/index.html'
    }),
    new HtmlWebpackPlugin({
      template:'./src/html/oop.html',
      filename:'html/oop.html'
    }),
    new PurifyCSSPlugin({
      // Give paths to parse for rules. These should be absolute!
      paths: glob.sync(path.join(__dirname, 'src/*.html')), }),
      // ProvidePlugin是webpack自帶的外掛,可以用此外掛全域性的引入所要使用的js庫
      new webpack.ProvidePlugin({ $:"jquery" })
  ],
  // 這款外掛用於壓縮 JS 程式碼,減少資源體積大小
  devServer: {
    //設定基本目錄結構
    contentBase: "./dist",//本地伺服器所載入的頁面所在的目錄 || contentBase:path:path.resolve(__dirname,'dist')
    //伺服器的IP地址,可以使用IP也可以使用localhost
    host:'localhost',
    //服務端壓縮是否開啟
    compress:true,
    //配置服務埠號
    port:5200,
    historyApiFallback: true,//不跳轉
    inline: true//實時重新整理
  } 
};

複製程式碼

pake.josn

{
  "name": "md",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dv": "webpack --mode development",
    "bd": "webpack --mode production",
    "server": "webpack-dev-server  --open"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "html-withimg-loader": "^0.1.16",
    "jquery": "^3.3.1",
    "npm": "^6.0.1",
    "to": "^0.2.9",
    "update": "^0.7.4"
  },
  "devDependencies": {
    "autoprefixer": "^8.5.0",
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.4",
    "babel-preset-env": "^1.7.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "css-loader": "^0.28.11",
    "extract-text-webpack-plugin": "^4.0.0-beta.0",
    "file-loader": "^1.1.11",
    "html-webpack-plugin": "^3.2.0",
    "less": "^3.0.4",
    "less-loader": "^4.1.0",
    "postcss-loader": "^2.1.5",
    "purify-css": "^1.2.5",
    "purifycss-webpack": "^0.7.0",
    "style-loader": "^0.21.0",
    "uglifyjs-webpack-plugin": "^1.2.5",
    "url-loader": "^1.0.1",
    "webpack": "^4.8.3",
    "webpack-cli": "^2.1.3",
    "webpack-dev-server": "^3.1.4"
  }
}

複製程式碼

相關文章