學(xué)習(xí)webpack的筆記

好久沒有寫日記了溉仑。吊说。吧兔。
今天我專心學(xué)習(xí)webpack磷仰,跟著網(wǎng)上的文章請練完這16個webpack小例子
翻譯阮一峰大神的demo來學(xué)。

Demo01:Entry file(入口文件)

首先下載來的webpack版本是4.6.0
我寫好package.json

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server --open",    //  npm run dev 熱更新
    "build": "webpack -p"    //  npm run build  打包
  },

執(zhí)行語句npm run dev境蔼,發(fā)現(xiàn)有錯誤灶平,啊,我才開始學(xué)箍土,就報錯逢享,內(nèi)容如下

The CLI moved into a separate package: webpack-cli.
Please install 'webpack-cli' in addition to webpack itself to use the CLI.
-> When using npm: npm install webpack-cli -D
-> When using yarn: yarn add webpack-cli -D

要命啊,我不懂啊吴藻,我之前命名全局安裝過腳手架瞒爬,為什么他現(xiàn)在又要我安裝一次,哎沟堡?-D是什么鬼侧但,好的,百度
-D原來就是--save-dev航罗。俊犯。。伤哺。
百度后燕侠,得知,webpack4.0開始就有些不同立莉,根據(jù)網(wǎng)上經(jīng)驗(yàn)者提及绢彤,如

在webpack 3中,webpack本身和CLI都在同一個包中蜓耻,但是在版本4中茫舶,他們將兩者分開來更好地管理它們。

所以我要重新裝一次CLI....

在項(xiàng)目目錄下要本地安裝webpack
npm install webpack-cli -D

webpack.config.js文件的變化
webpack.config.js里的配置刹淌,不再支持 module下的loaders饶氏,需要把loaders改成rules。
在項(xiàng)目目錄下必須使用配置文件webpack.config.js

即如下:

// webpack 必須采用 commonjs 寫法

//專門處理路徑用的有勾,以當(dāng)前路徑解析出一個絕對路徑
let path = require('path');
console.log(path.resolve('./dist'));
console.log(path.resolve('./dist'));
module.exports = {

    //打包的入口文件webpack會自動查找相關(guān)的依賴進(jìn)行打包
    entry: './src/main.js',

    output: {
        filename: 'bundle.js', //打包后的名字
        path: path.resolve('./dist'), //必須使用個絕對路徑
    },
    module: {
        rules: [
            //針對css文件疹启,進(jìn)行對應(yīng)的loader處理
            { test: /\.css$/, loader: "style-loader!css-loader" }
        ]
    }
};

驚喜 webpack --display-error-details//帶上參數(shù)可以找出詳細(xì)的錯誤信息

Demo02: Multiple entry files (多入口文件)

疑惑:這個。蔼卡。喊崖。都翻譯成多頁面XXX的,我沒有看出來哪里多頁面啊荤懂?這不是多個js文件合成一個嗎茁裙?
有一個提示,又是webpack4.0版本與之前的差異

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/
只需要在package.json中添加配置項(xiàng):

"scripts": {

  "dev": "webpack --mode development",

  "build": "webpack --mode production"

}

接著報錯了节仿。晤锥。。找不到模塊廊宪?矾瘾??

ERROR in Entry module not found: Error: Can't resolve './src' in 'E:\godown.work\webpack_study\myseft-demos\MultipleEntryFiles'
resolve './src' in 'E:\godown.work\webpack_study\myseft-demos\MultipleEntryFiles'
  using description file: E:\godown.work\webpack_study\myseft-demos\MultipleEntryFiles\package.json (relative path: .)
    Field 'browser' doesn't contain a valid alias configuration
    using description file: E:\godown.work\webpack_study\myseft-demos\MultipleEntryFiles\package.json (relative path: ./src)
      no extension
        Field 'browser' doesn't contain a valid alias configuration
        E:\godown.work\webpack_study\myseft-demos\MultipleEntryFiles\src doesn't exist
      .wasm
        Field 'browser' doesn't contain a valid alias configuration
        E:\godown.work\webpack_study\myseft-demos\MultipleEntryFiles\src.wasm doesn't exist
      .mjs
        Field 'browser' doesn't contain a valid alias configuration
        E:\godown.work\webpack_study\myseft-demos\MultipleEntryFiles\src.mjs doesn't exist
      .js
        Field 'browser' doesn't contain a valid alias configuration
        E:\godown.work\webpack_study\myseft-demos\MultipleEntryFiles\src.js doesn't exist
      .json
        Field 'browser' doesn't contain a valid alias configuration
        E:\godown.work\webpack_study\myseft-demos\MultipleEntryFiles\src.json doesn't exist
      as directory
        E:\godown.work\webpack_study\myseft-demos\MultipleEntryFiles\src doesn't exist

終于找到原因了挤忙,寫錯單詞

module.exports = {  // 寫成module.exports
    entry:{            // 寫成enter
        bundle1: "./main1.js",
        bundle2: "./main2.js"
    },
    output: {
        filename: '[name].js'
    }
};

Demo03: Babel-loader(編譯器可以將es6語法轉(zhuǎn)成低版本[如es5語法]提高兼容性)

大神配的是react霜威,我要配vue...一把辛酸淚

  • main.js
import Vue from 'vue'
import App from './App.vue'

new Vue({
  el: '#app',
  template: '<App/>',
  components: { App }
})
  • App.vue
<template>
  <div id="app">
    <h3>拉開大接訪卡拉集散地立刻飛機(jī)阿斯科利的解放昆侖山搭街坊</h3>
  </div>
</template>
<script>
export default {
  name: 'app',
}
</script>
<style>

</style>
  • index.html
<html>
    <body>
        <script src="./main.js"></script>
        <div id="app"></div>
    </body>
</html>
  • 錯誤的package.json
{
  "name": "babyloader",
  "version": "1.0.0",
  "scripts": {
    "dev": "webpack-dev-server --open --development",
    "build": "webpack -p --production"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.6.0"
  }
}

先不管我webpack.config.js配的怎么樣,假設(shè)我config.js配好了册烈,然后我一運(yùn)行npm run dev
不知道為什么報錯戈泼。。赏僧。很奇怪大猛,給我展示了一些配置help

Initialization:
  --init             Initializes a new webpack configuration or loads a
                     addon if specified                                [boolean]
  --migrate          Migrate your webpack configuration from webpack 1 to
                     webpack 2                                         [boolean]
  --add              Adds a webpack component to your configuration file
                                                                       [boolean]
  --generate-loader  Generates a new webpack loader project            [boolean]
  --generate-plugin  Generates a new webpack plugin project            [boolean]

Config options:
  --config               Path to the config file
                         [string] [default: webpack.config.js or webpackfile.js]
  --config-register, -r  Preload one or more modules before loading the webpack
                         configuration      [array] [default: module id or path]
  --config-name          Name of the config to use                      [string]
  --env                  Environment passed to the config, when it is a function
  --mode                 Mode to use
                                 [string] [choices: "development", "production"]
...
...
...
Unknown argument: development
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! babyloader@1.0.0 dev: `webpack-dev-server --open --development`  //  這是重點(diǎn),原來我沒有寫mode
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the babyloader@1.0.0 dev script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\Administrator\AppData\Roaming\npm-cache\_logs\2018-04-18T07_19_32_191Z-debug.log
  • 正確的package.json
{
  "name": "babyloader",
  "version": "1.0.0",
  "scripts": {
    "dev": "webpack-dev-server --open --mode development",
    "build": "webpack -p --mode production"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.6.0"
  }
}
module.exports = {
    entry: './main.js',
    output: {
        filename: 'bundle.js'
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                  loader: 'babel-loader',
                  options: {
                    presets: ['es2015']
                  }
                }
            }
        ]
    }
}

新建一個.babelrc文件挽绩,內(nèi)容如下

{
    "presets": ["es2015", "stage-2"],
    "plugins": ["transform-runtime"]
}

配合這篇文章,再找以前的package.json看需要裝些什么驾中,差點(diǎn)忘記裝vue唉堪,vue-loader

npm install vue-loader vue-loader
npm install vue
npm install babel-plugin-transform-runtime -D
提示要裝preset "es2015"
npm install babel-preset-es2015 -D
提示要裝preset "stage-2"
npm install babel-preset-stage-2 -D
提示要裝  Can't resolve 'css-loader'
npm install css-loader -D
終端終于沒有報錯,但是瀏覽器控制臺報錯了
Uncaught SyntaxError: Unexpected identifier
先不管它肩民,看看上面那篇文章跟以前的package.json還有什么差要安裝的
npm install babel-core babel-runtime babel-preset-env -D

再配置一次webpack.config.js

module.exports = {
    entry: './main.js',
    output: {
        filename: 'bundle.js'
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                  loader: 'babel-loader',
                  options: {
                    presets: ['es2015','env']
                  }
                }
            },
            {
                test: /\.vue$/, 
                exclude: /node_modules/,
                use: 'vue-loader'
            },
        ]
    }
}
  • 最后的package.json
{
  "name": "babyloader",
  "version": "1.0.0",
  "scripts": {
    "dev": "webpack-dev-server --open --mode development",
    "build": "webpack -p --mode production"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "vue": "^2.5.16"
  },
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.4",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-env": "^1.6.1",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-stage-2": "^6.24.1",
    "babel-runtime": "^6.26.0",
    "css-loader": "^0.28.11",
    "vue-html-loader": "^1.2.4",
    "vue-loader": "^14.2.2",
    "vue-template-compiler": "^2.5.16",
    "webpack": "^4.6.0"
  }
}

編譯器終端沒有報錯唠亚,但是打開瀏覽器卻報錯了



2018-04-19 更新

搞了一下午,都不知道為什么持痰,我放開了灶搜,繼續(xù)走下一個demo

我回來了,index.html的main.js改成bundle.js并且放div下面(因?yàn)閖s中掛載#app)
index.html的main.js改成bundle.js原因:
main.js只是webpack的入口文件工窍,打包之后就不再是什么main.js了割卖,而我index.html引用了main.js,而瀏覽器是不支持你所寫的main.js模塊化的方式患雏。下面問題的回答那個人說的
webpack配置css-loader后鹏溯,在m瀏覽器報錯 require is not defined

Demo04: css-loader

運(yùn)行一峰大神的代碼沒有報錯的,但是為什么我完完全全copy一份運(yùn)行纵苛,要我安裝style-loader剿涮,css-loader的我都安裝好了啊言津。攻人。取试。為什么我瀏覽器會報這樣的錯



啊;澄恰K才ā!E钇隆T趁蕖!P伎取H蕖!U琢U人!為什么要要這樣對我W匣省N堪病!4掀獭;馈!A逄蕖H鼋啊!<怠凤类!
這里的原因也是03demo那樣,index.html引了main.js

Demo05: Image loader

要安裝url-loader蝶押、file-loader
webpack.config.js

module.exports = {
    entry: './main.js',
    output: {
        path: '/dist',
        filename: 'bundle.js'
    },
    module: {
        rules: [
            {
                test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
                use: [
                    {
                      loader: 'url-loader',
                      options: {
                        limit: 8192,     // 低于指定的限制時踱蠢,可以返回一個 DataURL。
                        mimetype: 'image/jpeg',       // 指定MIME類型
                        fallback: 'responsive-loader'   // 當(dāng)文件大于限制時棋电,指定loader處理茎截,默認(rèn)file-loader
                      }
                    }
                ]
            }
        ]
    }
}
預(yù)測結(jié)果
認(rèn)證

Demo06: CSS Module

實(shí)用性不強(qiáng)啊,我不干~跳過

Demo07: UglifyJs Plugin

壓縮代碼赶盔,我發(fā)現(xiàn)我沒有裝uglifyjs-webpack-plugin運(yùn)行dev的時候node_modules文件夾下有一個.cache緩存問價夾企锌,里面有uglifyjs-webpack-plugin文件夾。自帶的于未?撕攒?

  • index.html
<html>
    <body>
        <h1>js壓縮</h1>
        <script src="./bundle.js"></script>
    </body>
</html>
  • main.js
function a(s){
    let a = 1;
    alert(s);
    return a;
}
const t = a("hello sb");
console.log(t);
  • package.json
{
  "name": "uglywebpackplugin",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack-dev-server --open --mode development",
    "build": "webpack -p --mode production"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "uglifyjs-webpack-plugin": "^1.2.5",
    "webpack": "^4.6.0"
  }
}
  • webpack.config.js
const webpack = require('webpack');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
    entry: './main.js',
    output: {
        filename: 'bundle.js'
    },
    plugins: [
        new UglifyJsPlugin()
    ]
}

好奇怪陡鹃。。我有es6語法抖坪,居然不裝babel-loader也可以運(yùn)行萍鲸。。擦俐。神了脊阴。。蚯瞧。

Demo08: HTML Webpack Plugin and Open Browser Webpack Plugin

  • package.json
{
  "name": "html_openbrowser",
  "version": "1.0.0",
  "scripts": {
    "dev": "webpack-dev-server --open --mode development",
    "build": "webpack -p --colors"
  },
  "license": "ISC",
  "devDependencies": {
    "html-webpack-plugin": "^3.2.0",
    "open-browser-webpack-plugin": "0.0.5",
    "webpack": "^4.6.0",
    "webpack-cli": "^2.0.14"
  }
}
  • main.js
document.write('<h1>html-webpack-plugin可以打包多個頁面</h1>')
  • template.html
<html>
    <head></head>
    <body>
        
    </body>
</html>
  • webpack.config.js
const HtmlwebpackPlugin = require('html-webpack-plugin');   // 需要本地裝webpack
const OpenBrowserPlugin = require('open-browser-webpack-plugin');
const path = require('path');
module.exports = {
    entry: './main.js',
    output: {
        path: path.resolve(__dirname, "dist"), // string
        // 所有輸出文件的目標(biāo)路徑
        // 必須是絕對路徑(使用 Node.js 的 path 模塊)
        filename: "./js/bundle.js", // string 相對路徑
        // 「入口分塊(entry chunk)」的文件名模板(出口分塊嘿期?)

        // publicPath: "/assets/", // string
        // 輸出解析文件的目錄,url 相對于 HTML 頁面
    },
    plugins: [
        new HtmlwebpackPlugin({
            template: "./template.html",
            filename: "./index.html",
            // 1埋合、filename配置的html文件目錄是相對于webpackConfig.output.path路徑而言的备徐,不是相對于當(dāng)前項(xiàng)目目錄結(jié)構(gòu)的。
            // 2甚颂、指定生成的html文件內(nèi)容中的link和script路徑是相對于生成目錄下的蜜猾,寫路徑的時候請寫生成目錄下的相對路徑。
            inject: "head",
            minify: true    // 壓縮html
        })
    ]
}
打包出來后的目錄

dist目錄下的index.html

dist/js目錄下的bundle.js

我這里的webpack.config.js沒有配自動打開網(wǎng)頁西设,可能多頁面的時候設(shè)置比較好一點(diǎn)瓣铣。


2018-04-20 更新

Demo09: 設(shè)置環(huán)境變量

因?yàn)樯婕暗氖?code>process.env,node的變量贷揽,我一直搞不懂這什么鬼來的棠笑,看完在找一份相對完整的Webpack項(xiàng)目配置指南么?這里有webpack環(huán)境變量配置問題禽绪?
關(guān)于process這個屬性講解 Node.js中環(huán)境變量process.env的一些事詳解
現(xiàn)在我終于有點(diǎn)理解了蓖救。

只要輸出一下process.env,你就知道這個env對象根本沒有DEBUG印屁、NODE_ENV這些循捺,因?yàn)檫@些都是我們手動掛載上去的,這是(區(qū)分環(huán)境的)標(biāo)記雄人。

// webpack.config.js
module.exports = {
    entry: './main.js',
    output: {
        filename: 'bundle.js'
    }
}
// console.log('process         ',process);
console.log('process.env         ',process.env);
console.log('process.env.NODE_ENV         ',process.env.NODE_ENV);
console.log('process.env.DEBUG         ',process.env.DEBUG);

然后我就開始寫一個demo
package.json

{
  "name": "setenv",
  "version": "1.0.0",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server --open --mode development"
  },
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.6.0",      // 這個是webpack4.6標(biāo)配
    "webpack-cli": "^2.0.14"      // 這個是webpack4.6標(biāo)配
  }
}

main.js

function main(){
    console.log(1);
}
if(__DEV__){    // DEBUG為true
    main();
}else{
    console.log('DEBUG為false');
}

webpack.config.js

const webpack = require('webpack');
// const path = require('path');

module.exports = {
    entry: './main.js',
    output: {
        filename: 'bundle.js'
    },
    plugins: [
        new webpack.DefinePlugin({
            __DEV__: JSON.stringify(JSON.parse(process.env.DEBUG || 'false'))   // 獲取DEBUG的值
        })
    ]
}
console.log('process.env.DEBUG    ',process.env.DEBUG);
console.log('typeof process.env.DEBUG    ',typeof process.env.DEBUG);
console.log("JSON.parse(process.env.DEBUG || 'false')    ",JSON.parse(process.env.DEBUG || 'false'));
console.log("typeof JSON.parse(process.env.DEBUG || 'false')    ",typeof JSON.parse(process.env.DEBUG || 'false'));
console.log("JSON.stringify(JSON.parse(process.env.DEBUG || 'false'))    ",JSON.stringify(JSON.parse(process.env.DEBUG || 'false')));
console.log("typeof JSON.stringify(JSON.parse(process.env.DEBUG || 'false'))    ",typeof JSON.stringify(JSON.parse(process.env.DEBUG || 'false')));
// console.log('process         ',process);
// console.log('process.env         ',process.env);
// console.log('process.env.NODE_ENV         ',process.env.NODE_ENV);
// console.log('process.env.DEBUG         ',process.env.DEBUG);

index.html 這是為了看效果~

<html>
    <body>
        <script src="./bundle.js"></script>
    </body>
</html>

運(yùn)行npm run dev从橘,好了,發(fā)現(xiàn)問題~

掛載失敗~

逛到跟我有同樣情況出現(xiàn)的人兒~process.env.NODE_ENV在哪兒設(shè)置础钠,最終被指引到使用cross-env解決跨平臺設(shè)置NODE_ENV的問題
這種只能解決在script里設(shè)置變量恰力,我想在命令行里設(shè)置。旗吁。踩萎。
向惡勢力低頭~~~
我發(fā)現(xiàn)不用安裝這個插件也可,就是在pageage.json配置script屬性set就行

Demo10: Code splitting

重點(diǎn)是require.ensure這個api
但是require跟require.ensure好想很钓。香府。董栽。到底有什么區(qū)別~
vue項(xiàng)目優(yōu)化之按需加載組件-使用webpack require.ensure
vue按需加載組件-webpack require.ensure
12. 異步加載模塊 require.ensure

最重點(diǎn)就是這句話了

看文章的例子結(jié)合這句話
其次,require.ensure使得dependenciescallback引用的模塊會打包到一個chunk中企孩,require引用的模塊會打包到bundle.js中锭碳。

// firstLoad.js
module.exports = {
    temp: function(b){
        console.log('執(zhí)行傳進(jìn)來的函數(shù)',b());
    }
}

// second.js
module.exports = {
    b:function(){
        return 10;
    }
}

// third.js
module.exports = "我是第三個加載"

// webpack.config.js
module.exports = {
    entry: './main.js',
    output: {
        filename: 'bundle.js'
    }
}
//  main.js

// require(['./third']); // 被打包到0.bundle.js里去
// require('./third'); // 被打包到bundle.js里去  勝出
function a(){
    console.log('a函數(shù)開始執(zhí)行');
    // require(['./third']); // 被打包到0.bundle.js里去
    require.ensure(['./second.js'],function(require){
        // 先加載second.js  注意點(diǎn):requi.ensure的模塊只會被下載下來,不會被執(zhí)行柠硕,只有在回調(diào)函數(shù)使用require(模塊名)后工禾,這個模塊才會被執(zhí)行运提。
        console.log('require.ensure開始執(zhí)行');
        var second = require("./second.js");    // 有一個b函數(shù)蝗柔,返回10
        var first = require("./firstLoad.js");  // 有一個temp函數(shù),輸出b()
        first.temp(second.b);
        
    },'a')
    // second.js  firstLoad.js  在    a.bundle.js
}
// main();
a();

package.json 就兩個依賴 webpack webpack-cli民泵,這里我就不貼了


結(jié)果

先加載bundle.js癣丧,按需加載a.bundle.js
多看文章~

Demo12: SplitChunksPlugin(Common chunk)

在webpack 4.X中棄用了Common chunk,代替它的是SplitChunksPlugin
官網(wǎng)介紹SplitChunksPlugin的譯文
根據(jù)該文章 webpack4: 代碼分割CommonChunkPlugin的壽終正寢 理解了SplitChunksPlugin栈妆,但是真正并沒有深入理解到位胁编。里面說的例子都說明一個理,當(dāng)共同chunk大于30kb(默認(rèn)30kb)并至少引用一次都會自動分離出來(這個說明還不夠嚴(yán)禁鳞尔,配合配置項(xiàng)才能準(zhǔn)確說明)嬉橙。

  • package.json(因?yàn)橛衑s6語法,所以需要babel)
    {
      "name": "splitchunkplugin",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "dev": "webpack-dev-server --open --mode development",
        "build": "webpack -p --mode production"
      },
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "babel-core": "^6.26.0",
        "babel-loader": "^7.1.4",
        "babel-plugin-transform-runtime": "^6.23.0",
        "babel-preset-env": "^1.6.1",
        "babel-preset-es2015": "^6.24.1",
        "babel-preset-stage-2": "^6.24.1",
        "babel-runtime": "^6.26.0",
        "css-loader": "^0.28.11",
        "html-webpack-plugin": "^3.2.0",
        "vue-loader": "^14.2.2",
        "vue-template-compiler": "^2.5.16",
        "webpack": "^4.6.0",
        "webpack-cli": "^2.0.15",
        "webpack-dev-server": "^3.1.3"
      },
      "dependencies": {
        "react": "^16.3.2",
        "react-dom": "^16.3.2",
        "vue": "^2.5.16"
      }
    }
    
  • webpack.config.js(多入口文件引用相同js寥假,輸出文件名由entry.key決定市框,chunkname由splitChunks.name決定)
      module.exports = {
          entry: {
              main1: './main1.js',
              main2: './main2.js',
              main3: './main3.js',
              main4: './main4.js',
          },
          output: {
              path: __dirname + '/dist',
              filename: './js/[name].js',
              chunkFilename: './js/[name].js', // 這里輸出的chunkname就是splitChunks配置的name
          },
          module: {
              rules: [
                  {
                      test: /\.js$/,
                      exclude: /node_modules/,
                      use: {
                      loader: 'babel-loader',
                      options: {
                          presets: ['es2015','env','stage-2'],
                          plugins: ["transform-runtime"]
                      }
                      }
                  },
                  {
                      test: /\.vue$/, 
                      exclude: /node_modules/,
                      use: 'vue-loader'
                  },
              ]
          },
          optimization: {
              splitChunks: {
                  chunks: "initial",    // 默認(rèn)all,   initial  分離后   因?yàn)楦淖兂跏即a塊會影響聲明在HTML的script標(biāo)簽糕韧。
                  minSize: 0,  //  形成一個新代碼塊最小的體積 byte單位  chunk超過才分離出來  默認(rèn)30000  太小體積的代碼塊被分割枫振,可能還會因?yàn)轭~外的請求,拖慢加載性能
                  minChunks: 1,   // (默認(rèn)是1):在分割之前萤彩,這個代碼塊最小應(yīng)該被引用的次數(shù)(譯注:保證代碼塊復(fù)用性粪滤,默認(rèn)配置的策略是不需要多次引用也可以被分割)
                  maxAsyncRequests: 5,    // 默認(rèn)是(5):按需加載時候最大的并行請求數(shù)。
                  maxInitialRequests: 3,  // 默認(rèn)是(3):分離后  一個入口最大的并行請求數(shù)
                  automaticNameDelimiter: '~',    // vendors~main1~main2.js雀扶,main1~main2.js
                  name: true,
                  cacheGroups: {
                      vendors: {
                          test: /[\\/]node_modules[\\/]/,     // 應(yīng)用來自node_modules的代碼杖小。
                          priority: -10   // 優(yōu)先級  更高優(yōu)先級的緩存組可以優(yōu)先打包所選擇的模塊
                      },
                      default: {
                          minChunks: 2,
                          priority: -20,
                          reuseExistingChunk: true    // webpack會添加一個只包含運(yùn)行時(runtime)額外代碼塊到每一個入口。(譯注:這個需要看場景使用愚墓,會導(dǎo)致每個入口都加載多一份運(yùn)行時代碼)
                      }
                  }
              }
          }
      }
    

optimization.splitChunks.chunks的值我寫了chunks
optimization.splitChunks.chunks的值我寫了0
都是為了方便有效果予权。。转绷。

  • main1.js伟件、main2.js、main3.js议经、main4.js斧账、apple.js谴返、boy.js
    // main1.js
      import Vue from "vue";
      import Apple from "./apple.js";
    
    // main2.js
      import Vue from "vue";
      import Apple from "./boy.js";
    
    // main3.js
      import React from "react";
      import Apple from "./apple.js";
    
    // main4.js
      import React from "react";
      import Apple from "./boy.js";
    
    // apple.js
      function apple(){
          console.log('這是apple插件');
      }
    
    // boy.js
      function boy(){
          console.log('這是boy插件');
      }
    
結(jié)果

默認(rèn)模式會將所有來自node_modules的模塊分配到一個叫vendors的緩存組;
所有重復(fù)引用至少兩次的代碼咧织,會被分配到default的緩存組嗓袱。

所有重復(fù)引用至少兩次的代碼,會被分配到default的緩存組习绢。這個我之后添加多一個main5.js入口文件引用apple.js打包之后也沒有出現(xiàn)default開頭的js文件生成渠抹,只有 main1~main3~main5.js

打包出來以后,除了自身的輸出文件main1/2/3/4.js生成以外闪萄,加載入口文件main1梧却、2.js時,都引用了vue败去,來自于node_modules的模塊放航,所以會有一個 vendors~main1~main2.js文件,同理圆裕,會有vendors~main3~main4.js广鳍,而main1.js、main3.js引用了apple.js吓妆,main2.js赊时、main4.js引用了boy.js,引用的模塊不是node_modules的模塊行拢,所以沒有vendor開頭祖秒,生成的是main1~main3.jsmain2~main4.js

官方推薦使用默認(rèn)配置

又不能完全理解每個屬性干嘛剂陡,還是乖乖的用默認(rèn)配置吧狈涮。。鸭栖。


2018.04.24更

Demo13: Vendor chunk 這個demo用的也是棄用的Common chunk歌馍,就是把第三方庫導(dǎo)出來用,這一功能SplitChunksPlugin自動解決了晕鹊,不寫此demo松却。

Demo14: Exposing global variables

全局暴露變量,說的很簡單溅话,但其實(shí)里面包含加載方式晓锻,運(yùn)行環(huán)境這些東西
這篇文章使我理解externals和libraryTarget的關(guān)系。webpack之深入淺出externals
webpack externals 深入理解
這篇文章使我能夠理解一點(diǎn)為什么要在html引入js之后飞几,還要在config配置砚哆,在js require。webpack的externals的使用

我一開始認(rèn)為屑墨,不把第三方打包到bundle躁锁,那安裝的時候-D就好了啊纷铣,為什么要特意說明不想讓webpack打包,直到看到下面這句話战转。在運(yùn)行時從外部獲取這些擴(kuò)展依賴搜立,哦,如果-D在生產(chǎn)環(huán)境下是沒有這個第三方的槐秧,他要在生產(chǎn)環(huán)境運(yùn)行這個第三方啄踊,所以要暴露~

[externals]防止將某些 import 的包(package)打包到 bundle 中,而是在運(yùn)行時(runtime)再去從外部獲取這些擴(kuò)展依賴

百著百著刁标,看到有人問externalsprovideplugin區(qū)別 Webpack ProvidePlugin vs externals?
我想了一下provideplugin颠通,Demo13: Vendor chunk 最后說到了provideplugin。
說到區(qū)別命雀,我也想知道有什么區(qū)別蒜哀,所以我就先搞一下provideplugin

純凈版 require,沒有provideplugin吏砂,沒有externals
  • package.json
{
  "name": "provideplugin_externals",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack-dev-server --open --mode development",
    "build": "webpack -p"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "html-webpack-plugin": "^3.2.0",
    "webpack": "^4.6.0",
    "webpack-cli": "^2.0.15",
    "webpack-dev-server": "^3.1.3"
  },
  "dependencies": {
    "jquery": "^3.3.1"
  }
}
  • webpack.config.js
let Htmlwebpackplugin = require('html-webpack-plugin');
let webpack = require('webpack');
module.exports = {
    entry: './main.js',
    output: {
        path: __dirname + '/dist',
        filename: 'bundle.js'
    },
    plugins: [
        new Htmlwebpackplugin({
            template: './index.html',
            inject: 'head',
            filename: 'main.html'
        })
    ]
}
  • main.js
let $ = require('jquery');
 $(function(){
     $('.a').text('wahahahaha');
 })
  • index.html 模版
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
</head>
<body>
    <div class="a"></div>
</body>
</html>

npm run build 運(yùn)行打包出來以后的size,安裝jquery乘客,require('jquery')狐血,打包到bundle了

總結(jié):安裝jquery后,require模塊會被打包到bundle中

provideplugin

webpack的ProvidePlugin配置
一開始看官網(wǎng)怎么使用這個插件易核,我還想著究竟要不要本地安裝jquery匈织,經(jīng)過我第一次試驗(yàn)證明嫌褪,是要安裝的杰刽。

  • package.json
{
  "name": "provideplugin_externals",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack-dev-server --open --mode development",
    "build": "webpack -p"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "html-webpack-plugin": "^3.2.0",
    "webpack": "^4.6.0",
    "webpack-cli": "^2.0.15",
    "webpack-dev-server": "^3.1.3"
  },
  "dependencies": {
    "jquery": "^3.3.1"   // 本地安裝,生產(chǎn)環(huán)境需要
  }
}
  • webpack.config.js
let Htmlwebpackplugin = require('html-webpack-plugin');
let webpack = require('webpack');
module.exports = {
    entry: './main.js',
    output: {
        path: __dirname + '/dist',
        filename: 'bundle.js'
    },
    plugins: [
        new webpack.ProvidePlugin({
            $: 'jquery'  // 打包在bundle.js了
        }),
        new Htmlwebpackplugin({
            template: './index.html',
            inject: 'head',
            filename: 'main.html'
        })
    ]
}
  • main.js
$(function(){
    $('.a').text('wahahahaha');
})
// window.onload = function(){
//     document.getElementsByClassName('a')[0].innerHTML = "xixixixixixixixix";
// }
  • index.html 模版
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
</head>
<body>
    <div class="a"></div>
</body>
</html>

npm run build 運(yùn)行打包出來以后的size释树,安裝jquery碰逸,配置provideplugin乡小,被打包進(jìn)入了bundle

總結(jié):用ProvidePlugin進(jìn)行實(shí)例初始化后,jquery就會被自動加載并導(dǎo)入對應(yīng)的node模塊中(會打包到bundle.js中)饵史,不再需要import和require進(jìn)行引入满钟,本地安裝之后,可以直接在代碼中使用胳喷,你還可以把$換成其他字母

externals
  • package.json
{
  "name": "provideplugin_externals",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack-dev-server --open --mode development",
    "build": "webpack -p"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "html-webpack-plugin": "^3.2.0",
    "webpack": "^4.6.0",
    "webpack-cli": "^2.0.15",
    "webpack-dev-server": "^3.1.3"
  },
  "dependencies": {
    "jquery": "^3.3.1"   // 本地安裝湃番,生產(chǎn)環(huán)境需要
  }
}
  • webpack.config.js
let Htmlwebpackplugin = require('html-webpack-plugin');
let webpack = require('webpack');
module.exports = {
    entry: './main.js',
    output: {
        path: __dirname + '/dist',
        filename: 'bundle.js'
    },
    plugins: [
        new webpack.ProvidePlugin({
            $: 'jquery'  // 打包在bundle.js了
        }),
        new Htmlwebpackplugin({
            template: './index.html',
            inject: 'head',
            filename: 'main.html'
        })
    ],
    externals: {  // 注釋了這個配置,jquery就會被打包到bundle
        jquery: 'jQuery'
    }
}
  • main.js
let $ = require('jquery');
$(function(){
    $('.a').text('wahahahaha');
})
  • index.html 模版
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
</head>
<body>
    <div class="a"></div>
</body>
</html>
安裝jquery吭露,require('jquery')吠撮,配置externals,沒有打包到bundle

總結(jié):本地安裝jquery讲竿,require或import引入jquery模塊泥兰,就被打包到bundle中择浊,但是在config文件中配置externals,jquery就不會被打包到bundle中逾条。
但是琢岩,我在html引用了jquery,我就不用在main.js引入直接使用了师脂,而且也不會被打包到bundle中担孔,為什么還要多此一舉,在js文件require/import吃警,在config文件配置呢糕篇?難道還有人糾結(jié)第三方是否打包到bundle?
自問自答:這篇文章使我能夠理解一點(diǎn)為什么要在html引入js之后酌心,還要在config配置拌消,在js require。webpack的externals的使用


前段時間我一直看HMR(熱替換)安券,中文文檔提到需要熱替換的js要在最下面加

if (module.hot) {
  module.hot.accept('./library.js', function() {
    // 使用更新過的 library 模塊執(zhí)行某些操作...
  })
}

按著它那里的基礎(chǔ)配置確實(shí)是可以實(shí)現(xiàn)HMR的墩崩,但是真正的項(xiàng)目不可能這樣吧,難道我沒寫一個js都要在下面加一塊這樣的東西哦....太浪費(fèi)時間了侯勉,我寧愿自己從頭搭一個小東西鹦筹,我也不再繼續(xù)看HMR了,或者后面我會再拾起來址貌。在這個過程中铐拐,我有瀏覽到比較好的教程講解
7、HMR 模塊熱加載講解得很詳細(xì)练对,但是我按照他的做法并沒有實(shí)現(xiàn)遍蟋,大家可以去試一下。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末螟凭,一起剝皮案震驚了整個濱河市虚青,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赂摆,老刑警劉巖挟憔,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異烟号,居然都是意外死亡绊谭,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門汪拥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來达传,“玉大人,你說我怎么就攤上這事∠芨希” “怎么了宗弯?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長搂妻。 經(jīng)常有香客問我蒙保,道長,這世上最難降的妖魔是什么欲主? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任邓厕,我火速辦了婚禮,結(jié)果婚禮上扁瓢,老公的妹妹穿的比我還像新娘详恼。我一直安慰自己,他們只是感情好引几,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布昧互。 她就那樣靜靜地躺著,像睡著了一般伟桅。 火紅的嫁衣襯著肌膚如雪敞掘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天贿讹,我揣著相機(jī)與錄音渐逃,去河邊找鬼。 笑死民褂,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的疯潭。 我是一名探鬼主播赊堪,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼竖哩!你這毒婦竟也來了哭廉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤相叁,失蹤者是張志新(化名)和其女友劉穎遵绰,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體增淹,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡椿访,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了虑润。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片成玫。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出哭当,到底是詐尸還是另有隱情猪腕,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布钦勘,位于F島的核電站陋葡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏彻采。R本人自食惡果不足惜腐缤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望颊亮。 院中可真熱鬧柴梆,春花似錦、人聲如沸终惑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雹有。三九已至偿渡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間霸奕,已是汗流浹背溜宽。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留质帅,地道東北人适揉。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像煤惩,于是被迫代替她去往敵國和親嫉嘀。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容