帶你由淺入深探索webpack4(一)

 相信你或多或少也據說過webpack、gulp等這些前端構建工具。近年來webpack愈來愈火,能夠說成爲了前端開發者必備的工具。若是你有接觸過vue或者react項目,我想你應該對它有所瞭解。css

這幾天我從新整理了一下webpack中知識點,把一些經常使用到的總結出來,但願能幫助到你們以及加深本身對webpack的理解。html

(因爲我在寫這篇文章的時候webpack最新版本是4.3 若是某些配置有變動,請自行查看官方最新文檔。千萬別看中文文檔,坑太多了更新太慢,不少屬性都被棄用了,要看直接看英文的。)前端

 

一: 初識webpackvue

1.1 什麼是webpack?node

這個我直接引用官方文檔的介紹:react

Webpack 是當下最熱門的前端資源模塊化 管理和打包 工具。它能夠將許多鬆散的模塊按照依賴和規則打包成符合生產環境部署的前端資源。還能夠將按需加載的模塊進行代碼分割,等到實際須要的時候再異步加載。webpack

在這裏我就很少介紹了,百度一搜一大堆介紹,本文章主要是介紹webpack怎麼用。es6

 

1.2 安裝webpackweb

由於webpack是基於nodejs實現的,因此要安裝webpack,先得安裝nodechrome

nodejs的中文網址:http://nodejs.cn/

下載完node以後,直接傻瓜式安裝就好,接着,咱們打開命令行,看下node和vue的版本

當輸出版本號時,證實安裝成功。(建議node儘可能8.0版本以上 npm儘可能6.0版本以上)。

這裏我比較建議用淘寶的鏡像cnpm,npm在國內實在是太慢了。

npm install -g cnpm --registry=https://registry.npm.taobao.org

固然,若是你網速快的話,用npm命令也不要緊。

首先,咱們建立一個空的文件夾,就起名叫webpack吧,而後執行一下初始化命令

npm init -y

接着安裝webpack和webpack-cli(建議局部安裝,全局安裝webpack可能會致使webpack版本不一樣而沒法正常使用)

npm install webpack webpack-cli --save-dev 或者 cnpm install webpack webpack-cli -save-dev

 

 

1.3 webpack的初始化配置

首先咱們在本件的一級目錄下建立一個src文件,src文件夾內再建立一個inde.js文件和一個index.html文件

src/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>初始化配置</title>
</head>
<body>
<div id="root">hello word!</div>
<script src="index.js"></script>
</body>
</html>
 

src/js:

var root = document.getElementById('root');
var text = document.createElement('div');
text.innerText = "斌果歡迎你!"
root.append(text);

固然packagej.json文件也要配置一下。

刪除「main」入口配置添加"private"爲true

{
  "name": "webpack",
  "version": "1.0.0",
  "description": "",
  "private":true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.30.0",
    "webpack-cli": "^3.3.0"
  }
}

這樣作主要是爲了讓你的項目私有化,防止意外發布你的代碼。

接着,在一級目錄下再建立一個 webpack.config.js  這個主要是webpack的配置文件

webpack.config.js

const path = require('path');

module.exports = {
    entry:'./src/index.js',  //打包文件的入口
    output:{                 //打包文件的出口
        filename:'bundle.js',          //打包後的文件名
        path:path.resolve(__dirname,'dist')      //打包後文件存放的位置
    }
}

webpack使用的是common.js規範的語法,在webpack.config.js中設置了webpack打包的基本配置。

接着咱們在控制檯中直接運行

npx webpack

 再回到項目中的,發現多了一個dist文件夾。裏面有一個打包後的bundle.js文件,就這樣咱們就將這個簡單的項目打包成功了。

你或許會問npx是什麼,我怎麼歷來沒有用過,可能你一直都是在用npm run **  npx其實就是直接運行node_modules中的配置

固然你也能夠在package.json中配置一下,像這樣

配置以後你運用npm run bundle 效果其實和運行 npx webpack是同樣,其最終仍是運行npx webpack的命令.。

 

1.4 webpack的初次使用

在上一小節,你可能會以爲,這webpack打包完後好像也並無用,到底webpack是用來幹嗎的?這一小節,就帶你用用webpak。

繼續上一節,咱們在src下繼續建立header.js,connent.js、footer.js這三個文件.。

src/header.js

var root = document.getElementById('root');
var text = document.createElement('div');
text.innerText = "頭部內容"
root.append(text);

src/content.js

var root = document.getElementById('root');
var text = document.createElement('div');
text.innerText = "中部內容"
root.append(text);

src/footer.js

var root = document.getElementById('root');
var text = document.createElement('div');
text.innerText = "尾部內容"
root.append(text);

若是咱們想將這三個js同時引入到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>簡單實例</title>
</head>
<body>
    <div id="root">hello word!</div>
    <script src="header.js"></script>
    <script src="content.js"></script> 
    <script src="footer.js"></script>
</body>
</html>

這樣咱們要引入3個js  對性能的消耗是十分巨大的 ,加入有100個這樣的js文件,那咱們不就要引入100個js?  因而咱們想能夠能夠只引入一個inde.js。就像下面那樣:

咱們將src中引入的header、content、footer、index所有使用esModule語法以下

function header(){
    var root = document.getElementById('root');
    var text = document.createElement('div');
    text.innerText = "頭部內容"
    root.append(text);
}
export default header;
import header from './header'
import content from './content'
import footer from './footer'

header();
content();
footer();

當咱們打開html,就會發現報了個錯!

這是爲何呢?  由於瀏覽器根本都不認識import是什麼,是不認識es、common這些語言的,可是,webpack認識啊!

咱們直接運行     npx webpack

而後咱們index.html中直接引入打包後的bundle.js,就會神奇的發現他成功運行並且沒報錯。

由於webpack已經幫咱們將esModule語法轉化爲瀏覽器能識別的法語告訴瀏覽器我要引入這三個js。

 

 

 

2、webpack的核心經常使用配置

 

2.1 HtmlWebpackPlugin

在上一章能夠看到,當咱們打包完成後,要本身將打包後的js代碼引入到html文件中,這顯得不那麼智能。

HtmlWebpackPlugin插件作得工做就是在打包完成後,自動生成一個html文件,並將打包生成的js自動引入到html文件中。

首先安裝這個插件:  npm install html-webpack-plugin -D

安裝完成後,咱們須要在webpack.config.js中配置一下:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');  //++++導入插件

module.exports = {
    entry:'./src/index.js',  //打包文件的入口
    plugins:[
        new HtmlWebpackPlugin({
            template: 'src/index.html'   //++++其會根據該html文件做模板自動導入打包後的js ,然
        })                               //++++後將生成的html放到出口文件夾中
    ],                             
    output:{                 //打包文件的出口
        filename:'bundle.js',          //打包後的文件名
        path:path.resolve(__dirname,'dist')      //打包後文件存放的位置
    }
}

這樣的話就無須要咱們本身配置html  其會在出口文件夾自動生成打包後的html。

運行npx webpack後

=>

 

 

2.2 CleanWebpackPlugin

當咱們每次打包完文件後,都會生成一個新的dist文件覆蓋上一個dist文件,但若是上個dist中有一些其餘的文件沒有被覆蓋掉,就會成爲雜魚,當咱們屢次打包後,雜魚可能就會變得愈來愈多,嚴重影響開發。

CleanWebpackPlugin插件作得就是每次打包時都會刪除上一次打包的文件,而不是覆蓋,這就使得每一次打包後的文件都是嶄新的,而不會混合上一次遺留的文件。

首先安裝這個插件: npm install clean-webpack-plugin -D

接着配置一下webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');  //++++導入插件

module.exports = {
    entry:'./src/index.js',  //打包文件的入口
    plugins:[
        new HtmlWebpackPlugin({
            template: 'src/index.html'   //其會根據該html文件做模板自動導入打包後的js ,然
        }),                             //後將生成的html放到出口文件夾中
        new CleanWebpackPlugin()    //++++配置刪除的文件                              
    ],                             
    output:{                 //打包文件的出口
        filename:'bundle.js',          //打包後的文件名
        path:path.resolve(__dirname,'dist')      //打包後文件存放的位置
    }
}

運行npx webpack 後

 =>

 

 

 2.3 Mode配置

當咱們每次打包的時候都會提示以下警告 

這究竟是什麼呢? 其實就是叫咱們設置工做狀態,既mode

mode有兩種狀態,主要是用於代表當前開發狀態!

development: 開發模式    打包後代碼沒有被壓縮

production:    生產模式     打包後代碼被壓縮爲一行

 

 

2.4 SourceMap配置

當咱們的代碼報錯時,調試工具顯示的是打包後js的報錯行數,這樣咱們很難找到原代碼到底在哪報錯。

SourceMap主要用於開發模式下使用,其能展示出打包後文件與源文件的映射關係。

這究竟是怎麼用的呢? 查看下官方文檔能夠看到有這麼多參數,不急,慢慢來解釋:

 

+表示性能較好,-表示性能較差  eval、inline、cheap、module等能夠自由組合使用

none:不產生映射,速度最快。

eval:執行速度也很快,性能最好,當時代碼提示不全面。

source-map:  把映射文件生成到獨立的文件,通常不建議使用,打包速度過慢。

-inline-: 不單獨生成文件,將生成的映射文件以base64的格式插入到打包後的js文件中,精確顯示錯誤位置

-cheap-:代碼只顯示出錯代碼在第幾行,不精確顯示具體位置,有效提升打包效率。

-module-:不只提示本身的業務代碼是否出錯,還提示第三方模塊中的代碼是否出錯。

在開發環境中,建議使用:cheap-module-eval-source-map 

在生產環境中,上線代碼通常不設置devtool。若是想知道報錯位置,建議使用:cheap-module-source-map

由於咱們主要在開發環境下,因此咱們使用cheap-module-eval-source-map

 

 

 2.5資源管理配置

2.5.1 加載css、sass、css前綴

首先咱們先在src下建立一個index.css

src/index.css:

body{
    background-color: blue;
}

接着咱們在src中的index.js中導入css文件

src/index.js:

import header from './header'
import content from './content'
import footer from './footer'
import './index.css'    //+++引入css文件

header();
content();
footer();

因爲webpack是沒法識別以css後綴的文件,因此咱們要引入loader(翻譯官)幫咱們解析css.

咱們須要安裝一下loader:  npm install style-loader css-loader --save-dev

安裝完成後,咱們還須要在webpack.config.js中配置一下:

webpack.config.js:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');  //導入插件

module.exports = {
    mode:'development',
    devtool:'cheap-module-eval-source-map',   //+++映射
    entry:'./src/index.js',  //打包文件的入口
    module:{
        rules:[
            {
                test:/\.css$/,       //+++配置以css結尾的文件  
                use:[                //+++添加翻譯官,順序爲由下向上,由右向左
                    'style-loader',
                    'css-loader'
                ]
            }          
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({
            template: 'src/index.html'   //其會根據該html文件做模板自動導入打包後的js ,然
        }),                             //後將生成的html放到出口文件夾中
        new CleanWebpackPlugin()    //配置刪除的文件                              
    ],                             
    output:{                 //打包文件的出口
        filename:'bundle.js',          //打包後的文件名
        path:path.resolve(__dirname,'dist')      //打包後文件存放的位置
    }
}

因爲css翻譯官解析後webpack仍是不認識css文件,還須要使用style翻譯官去處理一下才能被webpack所解析。

運行npx webpack打包後,咱們直接打開dist下的index.html文件,就能夠看到css文件已經被成功引入.

加載sass也是相似,只須要添加一個sass-loader、node-sass就能夠了!在這裏就不加演示。

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

而加前綴的話,在不一樣瀏覽器前綴各有不一樣。

  • Trident內核:主要表明爲IE瀏覽器, 前綴爲-ms
  • Gecko內核:主要表明爲Firefox, 前綴爲-moz
  • Presto內核:主要表明爲Opera, 前綴爲-o
  • Webkit內核:產要表明爲Chrome和Safari, 前綴爲-webkit

在這裏咱們只須要引入postcss-loader和autoprefixer就能夠了

安裝一下 : npm install postcss-loader autoprefixer --save-dev

在根目錄下建立一個postcss.config.js文件

postcss.config.js:

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

接着在webpack.config.js修改一下loader

           {
                test:/\.css$/,       //配置以css結尾的文件  
                use:[                //添加翻譯官,順序爲由下向上,由右向左
                    'style-loader',
                    'css-loader',
                    'postcss-loader'       //+++配置前綴
                ]
            },
            {
                test:/\.scss$/,
                use:[
                    'style-loader',
                    'css-loader',
                    'sass-loader',   //配置sass翻譯官
                    'postcss-loader'   //+++配置前綴
                ]
            }      

可是若是咱們要在sass中再引入sass 這就會出錯,由於再引入的sass文件沒有通過翻譯官翻譯.

因此,咱們還須要配置一下sass

           {
                test:/\.scss$/,
                use:[
                    'style-loader',
                    {
                        loader:'css-loader',
                        options:{
                            importLoader:2,//+++若是sass文件還引入其餘sass,另外一個會從新從下向上開始解析
                            modules:true //+++開啓css模塊打包
                        }
                    },
                    'sass-loader',          //配置sass翻譯官
                    'postcss-loader'        //配置前綴
                ]
            }   

2.5.2 加載圖片、字體

加載圖片主要使用兩個loader分別爲 file-loader  url-loader

其兩個loader都是解析圖片。不過url-loader能夠將小圖片轉化成base64的格式存放到打包後的css中

咱們通常都是使用url-loader 這樣處理小圖片的時候就能夠更快加載而無需引用原圖片地址。

安裝: npm install url-loader file-loader -D

配置:

webpack.config.js:

          {
                test:/\.(png|jpg|gif|svg)$/,
                use:[
                    {
                        loader:'url-loader',
                        options:{
                            name:'[name].[ext]',
                            outputPath:'images/',
                            limit:8096  //+++小於4K的圖片轉化爲base64存放到打包後的js中
                        }
                    }
                ]

            }        

由於file-loader和url-loader能夠加載任何文件,因此咱們也能夠用其來加載字體文件

webpack.config.js:

           {
                test:/\.(woff|woff2|eot|ttf|otf)&/,
                use:[
                    'file-loader'
                ]

            }

 2.5.3加載es6語法

因爲不少低版本的瀏覽器都不支持ES6語法,因此,咱們須要將ES6語言轉換爲ES5的語法。

在之前我都是用babel-preset-es2015轉換的,如今官方推薦使用babel-preset-env轉換,咱們就使用官方推薦的來轉換吧.

因爲babel只轉換語法,須要使用babel-polyfill來支持新語法像promise這些。

首先咱們先安裝依賴  npm install babel-loader @babel/core babel-preset-env @babel/polyfill -D

接着咱們在webpack.config.js中配置一下

webpack.config.js:

{
                test: /\.js$/,
                exclude: /node_modules/,//不須要對第三方模塊進行轉換,耗費性能
                use:[
                    'babel-loader'
                ] 
       

            },

由於bebel配置的信息太多了,咱們能夠在根目錄下建立一個.babelrc文件

.babelrc:

{
    "presets": [
        [
            "babel-preset-env", {         
                "targets": {         //在這些版本以上的瀏覽器中不轉換爲es5
                    "chrome": "67",
                    "firfox":"60",
                    "edge":"17",
                    "safari":"11.1"
                },
                "useBuiltIns": "usage"
            }
        ]
    ]
}

最後咱們還須要在index.js中引入polyfill:

src/index.js:

import "@babel/polyfill";

可是若是在第三方模塊時使用@babel/polyfill會污染全局變量,因此咱們可使用runtime-transform插件

其與polifill相似,但不會污染全局變量其用法和上面差很少

咱們安裝一下:

npm install babel-runtime babel-plugin-transform-runtime -D

在.babelrc中添加配置就能夠了。

{
    "plugins": ["transform-runtime"]
}

更多的配置能夠參考官網文檔:babeljs.io/setup

 

 

2.6配置多個出入口文件

在目前,咱們一直以一個index.js爲入口,bundle.js文件爲出口,但隨着程序的增長,咱們可能須要輸出多個bundle文件。

這個很簡單,咱們新建一個print.js文件,並添加一些邏輯

import Header from './header'

Header();
console.log('這是打包的第二入口文件');

而後咱們只須要修改一下webpack.config.js中的出入口配置就能夠了。

webpack.config.js:

 entry:{
        main:'./src/index.js',       //打包入口文件
        print:'./src/print.js'
    },
......
 output:{
       filename:'[name].js',          //打包後的文件名
        path:path.resolve(__dirname,'dist')      //打包後文件存放的位置
     }

 

 

2.7熱更新配置

咱們每次打包的時候,都須要手動運行npm run bundle 或者npx webpack這顯得什麼繁瑣。

下面介紹幾個配置,能夠在代碼發生變化後自動編譯代碼。

2.7.1觀察模式watch

咱們只須要在package.json文件中添加一個用於啓動觀察模式的npm script腳本就能夠了;

{
  "name": "webpack",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "bundle": "webpack",
    "watch": "webpack --watch"    //+++添加啓動腳本
  },
   "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "autoprefixer": "^9.5.1",
    "clean-webpack-plugin": "^2.0.1",
    "css-loader": "^2.1.1",
    "file-loader": "^3.0.1",
    "html-webpack-plugin": "^3.2.0",
    "node-sass": "^4.11.0",
    "postcss-loader": "^3.0.0",
    "sass-loader": "^7.1.0",
    "style-loader": "^0.23.1",
    "url-loader": "^1.1.2",
    "webpack": "^4.30.0",
    "webpack-cli": "^3.3.0"
  }
}

這樣當咱們修改js中的代碼時,其會自動執行打包,咱們只須要刷新一下頁面就能夠看到變化。

2.7.2使用webpack-dev-server

當咱們使用watch時,咱們雖然能夠自動打包,可是頁面不能自動刷新,須要咱們手動刷新。

webpack-dev-server爲咱們提供了一個簡單的web服務器,可以實時從新加載。

咱們首先須要安裝一下: npm install webpack-dev-server -D

接着咱們須要修改webpack.config.js配置,告訴服務器,在哪裏查找文件。

webpack.config.js:

......

module.exports = {
    mode:'development',
    devtool:'cheap-module-eval-source-map',   //映射
    entry:{                     //配置入口文件
        main:'./src/index.js',
        print:'./src/print.js'
    },
    devServer:{
        contentBase:'./dist',      //+++配置運行目錄
        open:true,                 //+++自動打開瀏覽器
        port:8080,                 //+++服務器訪問端口
        proxy:{                    //+++配置跨越代理
            'api':'http://loacalhost:3000'
        }
    },
   ......
    plugins:[
        new HtmlWebpackPlugin({
            template: 'src/index.html'   //其會根據該html文件做模板自動導入打包後的js ,然
        }),                             //後將生成的html放到出口文件夾中
        new CleanWebpackPlugin()    //配置刪除的文件                              
    ],                             
    output:{                 //打包文件的出口
        filename:'[name].js',          //打包後的文件名
        path:path.resolve(__dirname,'dist')      //打包後文件存放的位置
    }
}

而後咱們只須要在package.json中添加一個script腳本用於啓動便可,

 "scripts": {
    "bundle": "webpack",
    "watch": "webpack --watch",
    "server": "webpack-dev-server"    //+++啓動wepack-dev-server
  },

運行npm webpack server 就能夠看到webpack已經啓動了一個服務器。

2.7.3使用webpack-dev-middleware

webpack-dev-middleware是一個容器,它能夠吧webpack處理後的文件傳遞給一個服務器。webpack-dev-server在內部就是使用了它。

這個僅僅瞭解就能夠了,不必本身寫一個server,且性能沒有webpack-dev-server好。這裏主要是配合express server來使用

首先咱們本身安裝一下:npm install express webpack-dev-middleware --save-dev

而後咱們須要在webpack.config.js中配置一下

output: {
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, 'dist'),
      publicPath: '/'      //+++
    }

接着咱們須要建立一個server.js

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');

const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);

// Tell express to use the webpack-dev-middleware and use the webpack.config.js
// configuration file as a base.
app.use(webpackDevMiddleware(compiler, {
  publicPath: config.output.publicPath
}));

// Serve the files on port 3000.
app.listen(3000, function () {
  console.log('Example app listening on port 3000!\n');
});

這時咱們只須要在package.json中添加一個srcipt腳本而後直接運行腳本就能夠了

"server": "node server.js",

 

 

2.8模塊熱替換(HMR)

當咱們啓動server時,若是修改某個模塊,它就會整個網頁從新刷新,以前的操做又得重來。

HMR就是容許運行時更新各類模塊,而不用徹底刷新。也就是隻更新有變更的模塊,其餘模板不動。

注:HMR只適合在開發環境下,並不適合在線上環境下配置。

由於HMR是webpack內置的插件,因此無需再下載,在使用以前,咱們先將print.js刪除。再引入HMR的相關配置。

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');  //導入插件
const webpack = require('webpack');     //+++導入webpack

module.exports = {
    mode:'development',
    devtool:'cheap-module-eval-source-map',   //映射
    entry:{                     //配置入口文件
        main:'./src/index.js'
    },
    devServer:{
        contentBase:'./dist',      //配置運行目錄
        open:true,                 //自動打開瀏覽器
        port:8080,                 //服務器訪問端口
        proxy:{                    //配置跨越代理
            'api':'http://loacalhost:3000'
        },
        hot:true,              //+++開啓熱更新
        hotOnly:true            //+++即便html錯誤,也不讓頁面更新,           
    },
    ......
    plugins:[
        new HtmlWebpackPlugin({
            template: 'src/index.html'   //其會根據該html文件做模板自動導入打包後的js ,然
        }),                             //後將生成的html放到出口文件夾中
        new CleanWebpackPlugin(),    //配置刪除的文件    
        new webpack.NamedModulesPlugin(),        //+++以便更容易查看要修補(patch)的依賴
        new webpack.HotModuleReplacementPlugin()      //+++使用模塊熱替換插件
    ],                             
    output:{                 //打包文件的出口
        filename:'[name].js',          //打包後的文件名
        path:path.resolve(__dirname,'dist')      //打包後文件存放的位置
    }
}

到這裏尚未完  要想實現熱替換,還要配置一下index.js

import header from './header'
import content from './content'
import footer from './footer'
import './index.css'    //引入css文件

header();
content();
footer();

//若是模塊啓用了HMR,就能夠用 module.hot.accept(),監聽模塊的更新。
if (module.hot) {
    module.hot.accept('./header.js', function() {
       header()
    })
  }
  

當咱們單修改header.js時,其餘模塊並不會影響,只會更新header模塊的內容。但咱們會發現修改header會建立一個新的dom。

這是由於咱們每次更新header模塊都建立了一個dom 咱們須要先修改一下js代碼在更新前先清除以前添加的dom節點。

因此在使用HMR時要根據不一樣的代碼作相應的設置。

HMR修改樣式表

這個就更簡單了,其實在上面咱們應該實現了這個功能,無須作任何修改,當咱們修改css樣式時,其餘模塊是不會刷新的。無需設置module.hot.accept。

由於style-loader已經幫咱們在後臺使用 module.hot.accept 來修補(patch) <style> 標籤。

 

 

2.9 tree shaking

在咱們編寫代碼時或引入第三方庫的時候,不少時候會引入不少冗餘的代碼,不經意間增大了性能的消耗。

tree shaking是一個術語,一般用於描述移除JavaScript上下問中未引用的代碼,其只支持es6模塊例如import和export。

實現這個功能很簡單,只須要在package.json中配置「sideEffects」屬性就能實現。

"sideEffects":["*.css"],   //+++對全部css不使用Tree shaking。

若是將其設置爲false則對全部使用tree shaking。若是不想怕誤刪的文件能夠寫在數組裏。

在生產環境中,其會自動壓縮打包,無需設置optimization,若是在開發環境中仍是要配置一下的。

webpack.config.js:

......
module.exports = { mode:'development', devtool:'cheap-module-eval-source-map', //映射 entry:{ //配置入口文件 main:'./src/index.js' }, ...... optimization:{ //+++在開發環境中配置,生產環境不用 usedExports:true }, output:{ //打包文件的出口 filename:'[name].js', //打包後的文件名 path:path.resolve(__dirname,'dist') //打包後文件存放的位置  } }

 

 

2.10生產環境構建

在咱們以前的開發中一直都是以開發環境開發爲主,然而生產環境與開發環境有很大的區別,在開發環境中,注重的是怎樣使開發更便利,而在生產環境中注重的是若是使代碼性能更高,簡而精。因此咱們頗有必要將開發環境和生產環境分離出來。

在這裏咱們應該抽取出他們的公共部分,再將它們與公共配置分別合併在一塊兒,這時,咱們就須要一個工具:webpack-merge

首先,咱們先安裝一下這個工具。

npm isntall webpack-merge -D

而後咱們須要建立三個文件:webpack.common.js、webpack.dev.js、webpack.prod.js。咱們將公共部分抽離到webpack.common.js中,刪除掉webpack.config.js

 webpack.common.js:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin'); //導入插件 const webpack = require('webpack'); //導入webpack  module.exports = { entry:{ //配置入口文件 main:'./src/index.js' }, module:{ rules:[ { test: /\.js$/, exclude: /node_modules/,//不須要對第三方模塊進行轉換,耗費性能  use:[ 'babel-loader' ] }, { test:/\.css$/, //配置以css結尾的文件 use:[ //添加翻譯官,順序爲由下向上,由右向左 'style-loader', 'css-loader', 'postcss-loader' //配置前綴  ] }, { test:/\.scss$/, use:[ 'style-loader', { loader:'css-loader', options:{ importLoader:2,//若是sass文件還引入其餘sass,另外一個會從新從下向上解析 modules:true //開啓css模塊打包  } }, 'sass-loader', //配置sass翻譯官 'postcss-loader' //配置前綴  ] }, { test:/\.(png|jpg|gif|svg)$/, use:[ { loader:'url-loader', options:{ name:'[name].[ext]', outputPath:'images/', limit:8096 //小於4K的圖片轉化爲base64存放到打包後的js中  } } ] }, { test:/\.(woff|woff2|eot|ttf|otf)&/, use:[ 'file-loader' ] } ] }, plugins:[ new HtmlWebpackPlugin({ template: 'src/index.html' //其會根據該html文件做模板自動導入打包後的js ,然 }), //後將生成的html放到出口文件夾中 new CleanWebpackPlugin() //配置刪除的文件  ], output:{ //打包文件的出口 filename:'[name].js', //打包後的文件名 path:path.resolve(__dirname,'dist') //打包後文件存放的位置  } }

webpack.dev.js:

const webpack = require('webpack');     //導入webpack
const merge = require('webpack-merge');
const common = require('./webpack.common'); module.exports = merge(common,{ mode:'development', devtool:'cheap-module-eval-source-map', devServer:{ contentBase:'./dist', //配置運行目錄 open:true, //自動打開瀏覽器 port:8080, //服務器訪問端口 hot:true //開啓熱更新  }, plugins:[ new webpack.NamedModulesPlugin(), //以便更容易查看要修補(patch)的依賴 new webpack.HotModuleReplacementPlugin() //使用模塊熱替換插件  ], optimization:{ //在開發環境中配置,生產環境不用 usedExports:true } })

webpack.prod.js:

const merge = require('webpack-merge');
const common = require('./webpack.common'); module.exports = merge(common,{ mode:'production', devtool:'cheap-module-source-map' })

 接着咱們只需在package.json中配置一下script腳本,運行不一樣的腳本進行不一樣環境下的打包

package.json:

 "dev":"webpack-dev-server --config ./webpack.dev.js",    "build":"webpack --config ./webpack.prod.js"          
相關文章
相關標籤/搜索