1. 程式人生 > >Webpack 學習總結

Webpack 學習總結

內部 彩色 配置示例 sets 默認 actions 參考 想要 gin

1.Webpack的特性

webpack 模塊打包機,分析你的項目結構,找到JavaScript模塊以及其他一些瀏覽器不能直接運行的拓展語言(Scss,TypeScript等),將其打包為合適的格式以供瀏覽器使用。

webpack具有requireJs和browserify的功能,但仍有很多自己的新特性:

1. 對 CommonJS 、 AMD 、ES6的語法做了兼容

2. 對js、css、圖片等資源文件都支持打包

3. 串聯式模塊加載器以及插件機制,讓其具有更好的靈活性和擴展性,例如提供對CoffeeScript、ES6的支持

4. 有獨立的配置文件webpack.config.js

5. 可以將代碼切割成不同的chunk,實現按需加載,降低了初始化時間

6. 支持 SourceUrls 和 SourceMaps,易於調試

7. 具有強大的Plugin接口,大多是內部插件,使用起來比較靈活

8.webpack 使用異步 IO 並具有多級緩存。這使得 webpack 很快且在增量編譯上更加快

Webpack和Grunt, Gulp的區別:

Grunt和Gulp的工作方式是:在一個配置文件中,指明對某些文件進行類似編譯,組合,壓縮等任務的具體步驟,然後這個工具自動替你完成這些任務。(Do a series of tasks)

Webpack的工作方式是,把項目當做一個整體,通過給定一個主文件entry(index.js),Webpack 將從這個文件開始找到項目的所有依賴文件,使用loaders處理他們,最後打包為瀏覽器可識別的JavaScript文件。(從入口文件查找下載依賴) 效率更高,打包更好。

2.開始使用Webpack

webpack 可以作為全局的npm模塊安裝,也可以在當前項目中安裝。

npm install -g webpack

npm install --save-dev webpack

在終端的最基礎命令:webpack {entry file/入口文件} {destination for bundled file/存放bundle.js的地方} 只需要一個入口文件,webpack將自動識別項目所依賴的其他文件。

如果是非全局安裝,直接在命令行下執行 node_modules/.bin/webpack,就會自動讀取webpack.config.js文件中的配置,輸出打包後的文件。

在項目的package.son 文件中配置,實現快速打包:

{
  "name": "webpack-sample-project",
  "version": "1.0.0",
  "description": "Sample webpack project",
  "scripts": {
    "start": "webpack"      //配置的地方就是這裏啦,相當於把npm的start命令指向webpack命令
  },
  "author": “dd”,
  "license": "ISC",
  "devDependencies": {
    "webpack": "^1.13.2",
  }
}

在項目中通過配置webpack.config.js 文件來使用Webpack, Webpack的強大功能都體現在配置文件中。下面是一個基本配置示例:

var path = require(‘path‘);

module.exports = {
    entry: path.resolve(__dirname, ‘./src/index.js‘), //已多次提及的唯一入口文件

    output: {
        path: path.resolve(__dirname, ‘./bundle‘), //打包後的文件存放的地方

        filename: ‘bundle.js‘   //打包後輸出文件的文件名

    },

    module: {
        loaders: [
            { test: /\.js?$/, loaders: [‘babel‘], exclude: /node_modules/ },
            { test: /\.js$/, loader: ‘babel-loader‘, exclude: /node_modules/}
        ]
    },

    resolve:{
        extensions:[‘‘,‘.js‘,‘.json‘]
    },
};

註:“__dirname”是node.js中的一個全局變量,它指向當前執行腳本所在的目錄。

(1)entry

entry參數定義了打包後的入口文件,可以是個字符串或數組或者是對象;如果是數組,數組中的所有文件會打包生成一個filename文件;如果是對象,可以將不同的文件構建成不同的文件。

{

    entry: {

        page1: "./page1",

        //支持數組形式,將加載數組中的所有模塊,但以最後一個模塊作為輸出

        page2: ["./entry1", "./entry2"]

    },

    output: {

        path: "dist/js/page",

        publicPath: "/output/",

        filename: "[name].bundle.js"

    }

}

該段代碼最終會生成一個 page1.bundle.js 和 page2.bundle.js,並存放到 ./dist/js/page 文件夾下

(2)output

output參數是個對象,定義了輸出文件的位置及名字:

output: {

        path: "dist/js/page",

        publicPath: "/output/",

        filename: "[name].bundle.js"

    }

path: 打包文件存放的絕對路徑

publicPath: 網站運行時的訪問路徑

filename:打包後的文件名

當我們在entry中定義構建多個文件時,filename可以對應的更改為[name].js用於定義不同文件構建後的名字。

(3)module

module: {

        //加載器配置

        loaders: [

            //.css 文件使用 style-loader 和 css-loader 來處理

            { test: /\.css$/, loader: ‘style-loader!css-loader‘ },

            

            //.js 文件使用 jsx-loader 來編譯處理

            { test: /\.js$/, loader: ‘jsx-loader?harmony‘ },

            

            //.scss 文件使用 style-loader、css-loader 和 sass-loader 來編譯處理

            { test: /\.scss$/, loader: ‘style!css!sass?sourceMap‘},

           

            //圖片文件使用 url-loader 來處理,小於8kb的直接轉為base64

            { test: /\.(png|jpg)$/, loader: ‘url-loader?limit=8192‘}

        ]

    }

webpack中JavaScript,CSS,LESS,TypeScript,JSX,CoffeeScript,圖片等靜態文件都是模塊,不同模塊的加載是通過模塊加載器(webpack-loader)來統一管理的。loaders之間是可以串聯的,一個加載器的輸出可以作為下一個加載器的輸入,最終返回到JavaScript上。

(4)resolve

webpack在構建包的時候會按目錄的進行文件的查找,resolve屬性中的extensions數組中用於配置程序可以自行補全哪些文件後綴:

resolve: {

        //查找module的話從這裏開始查找

        root: ‘/pomy/github/flux-example/src‘, //絕對路徑


        //自動擴展文件後綴名,意味著我們require模塊可以省略不寫後綴名

        extensions: [‘‘, ‘.js‘, ‘.json‘, ‘.scss‘],


        //模塊別名定義,方便後續直接引用別名,無須多寫長長的地址

        alias: {

            AppStore : ‘js/stores/AppStores.js‘,//後續直接 require(‘AppStore‘) 即可

            ActionType : ‘js/actions/ActionType.js‘,

            AppAction : ‘js/actions/AppAction.js‘

        }

    }

然後我們想要加載一個js文件時,只要require(‘common‘)就可以加載common.js文件了。

註意一下, extensions 第一個是空字符串 ‘‘ 對應不需要後綴的情況.

(5)externals

當我們想在項目中require一些其他的類庫或者API,而又不想讓這些類庫的源碼被構建到運行時文件中,這在實際開發中很有必要。此時我們就可以通過配置externals參數來解決這個問題:

externals: {

"jquery": "jQuery"

}

(6)devtool使調試變得更容易

devtool選項 配置結果

source-map: 在一個單獨的文件中產生一個完整且功能完全的文件。這個文件具有最好的source map,但是它會減慢打包文件的構建速度;

cheap-module-source-map: 在一個單獨的文件中生成一個不帶列映射的map,不帶列映射提高項目構建速度,但是也使得瀏覽器開發者工具只能對應到具體的行,不能對應到具體的列(符號),會對調試造成不便;

eval-source-map: 使用eval打包源文件模塊,在同一個文件中生成幹凈的完整的source map。這個選項可以在不影響構建速度的前提下生成完整的sourcemap,但是對打包後輸出的JS文件的執行具有性能和安全的隱患。不過在開發階段這是一個非常好的選項,但是在生產階段一定不要用這個選項;

cheap-module-eval-source-map: 這是在打包文件時最快的生成source map的方法,生成的Source Map. 會和打包後的JavaScript文件同行顯示,沒有列映射,和eval-source-map選項具有相似的缺點;

(7)devServer 構建本地服務器

contentBase: 默認webpack-dev-server會為根文件夾提供本地服務器, 如果想為另外一個目錄下的文件提供本地服務器,應該在這裏設置其所在目錄

port: 設置默認監聽端口,如果省略,默認為”8080“

inline: 設置為true,當源文件改變時會自動刷新頁面

colors: 設置為true,使終端輸出的文件為彩色的

historyApiFallback: 在開發單頁應用時非常有用,它依賴於HTML5 history API,如果設置為true,所有的跳轉將指向index.html

(8)loader配置

通過使用不同的loader,webpack通過調用外部的腳本或工具可以對各種各樣的格式的文件進行處理,

比如說分析JSON文件並把它轉換為JavaScript文件,或者說把下一代的JS文件(ES6,ES7)轉換為現代瀏覽器可以識別的JS文件。

或者說對React的開發而言,合適的Loaders可以把React的JSX文件轉換為JS文件。

Loaders需要單獨安裝並且需要在webpack.config.js下的modules關鍵字下進行配置,

Loaders的配置選項包括以下幾方面:

test:一個匹配loaders所處理的文件的拓展名的正則表達式(必須)

loader:loader的名稱(必須)

include/exclude:手動添加必須處理的文件(文件夾)或屏蔽不需要處理的文件(文件夾)(可選);

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

安裝babel,babel具有非常多的配置選項,在單一的webpack.config.js文件中進行配置往往使得這個文件顯得太復雜,因此一些開發者支持把babel的配置選項放在一個單獨的名為 ".babelrc" 的配置文件中。如果不復雜,可以直接在webpack.config.js中進行配置。

{

      test: /\.jsx?$/,

      exclude: /node_modules/,

      loader: ‘babel-loader‘,

      options: {

        cacheDirectory: true,

        presets: [‘env‘, ‘stage-2‘, ‘react‘],

        plugins: [‘transform-runtime‘],

      },

   }

css Loader處理:

 test: /\.(less|css)$/,

  use: [

    {

      loader: ‘style-loader‘,

    },

    {

      loader: ‘css-loader‘,

      options: {

        minimize: false,

        sourceMap: true,

      },

    },

    {

      loader: ‘postcss-loader‘,

      options: {

        plugins: postcss, //自動添加適應不同瀏覽器的前綴

      },

    },

    {

      loader: ‘less-loader‘,

      options: {

        sourceMap: true,

      },

    },

  ]

npm一次性安裝多個依賴模塊,模塊之間用空格隔開,安裝babel 常用的依賴

npm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react

(9)plugins

const plugins = [

  // plugin for passing in data to the js, like what NODE_ENV we are in.

  new webpack.DefinePlugin(config.globals),

  new webpack.optimize.CommonsChunkPlugin({

    names: [‘common‘, ‘vendor‘, ‘manifest‘],

    minChunks: 2,

  }),

  new webpack.NoEmitOnErrorsPlugin(),

//Hot Module Replacement(HMR)也是webpack裏很有用的一個插件,它允許你在修改組件代碼後,自動刷新實時預覽修改後的效果。在webpack中實現HMR也很簡單,只需要做兩項配置。
/**在webpack配置文件中添加HMR插件,在Webpack Dev Server中添加“hot”參數;
      devServer: {

             hot: true

       }
*/

  new webpack.HotModuleReplacementPlugin(),


/**在入口文件中index.js中:

if (module.hot) {

 module.hot.accept(‘./home.js’); //接收這個文件的修改用來熱加載

  module.hot.accept(‘./routes‘, () => {  //路由的改變將造成熱加載,重新渲染

    render(createRouter)

  })

}
*/

  new webpack.NamedModulesPlugin(),

//HtmlWebpackPlugin 這個插件的作用是依據一個簡單的模板(index.template.html),
//幫你生成最終的Html5文件,這個文件中自動引用了你打包後的JS文件。每次編譯都在文件名中插入一個不同的哈希值。
new HtmlWebpackPlugin({ title: ‘ACTIVE Reader Cloud Dev‘, inject: true, chunksSortMode: ‘dependency‘, filename: ‘index.html‘, template: paths.base(‘build/index.template.html‘), })

]

在package.json文件中:

devDependencies 裏面的插件只用於開發環境,不用於生產環境,而 dependencies 是需要發布到生產環境的,安裝的時候註意控制。

3.Webpack3的新特性

6月20日發布了webpack3, 它和2有什麽區別?

(1)更新方法以及版本遷移

通過命令直接安裝即可,後面需要加上版本號。

npm install [email protected] --save-dev

2)scope hoisting

webpack2處理後的每個模塊均被一個函數包裹,如下:

/* 50 */

/***/ (function(module, __webpack_exports__, __webpack_require__) {

    window.lib = {}

    ...   

/* harmony default export */ __webpack_exports__["a"] = (window.lib);


/***/ }),

這樣會帶來一個問題:降低瀏覽器中JS執行效率,這主要是閉包函數降低了JS引擎解析速度。

於是webpack團隊參考Closure Compiler和Rollup JS,將一些有聯系的模塊,放到一個閉包函數裏面去,通過減少閉包函數數量從而加快JS的執行速度。

webpack3通過設置ModuleConcatenationPlugin使用這個新特性:

module.exports = { 

  plugins: [

    new webpack.optimize.ModuleConcatenationPlugin()

  ]

};

(3)Magic Comments

用於動態引入ES Module,webpack將傳入import方法的模塊打包到一個單獨的代碼塊(chunk),但是卻不能像require.ensure一樣,為生成的chunk指定chunkName,因此在webpack3中提出了Magic Comment用於解決該問題,用法如下:

import(/* webpackChunkName: "my-chunk-name" */ ‘module‘);

其實就是可以命令 chunk name 了.

Webpack接下來的還會持續有的新特性:

  • 更好的編譯緩存
  • 更快的首次以及增量編譯速度
  • 對 TypeScript 更加友好地支持
  • 修改 Long term caching
  • 增加對 WASM Module 的支持
  • 用戶體驗的改進

小夥伴們敬請期待吧...

Webpack 學習總結