webpack使用手冊


安裝

css

//全局安裝
npm install -g webpack
//安裝到你的項目目錄
npm install --save-dev webpack

 

正式使用Webpack前的準備

在終端中使用npm init命令能夠自動建立這個package.json文件html

npm init

package.json文件已經就緒,咱們在本項目中安裝Webpack做爲依賴包node

// 安裝Webpack
npm install --save-dev webpack

Webpack配置文件

module.exports = {
  entry:  __dirname + "index.js",//已屢次說起的惟一入口文件
  output: {
    path: __dirname + "/dist",//打包後的文件存放的地方
    filename: "bundle.js"//打包後輸出文件的文件名
  }
}

更快捷的執行打包任務

在package.json中對npm的腳本部分進行相關設置便可,設置方法以下。react

{
  "name": "webpack-sample-project",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "start": "webpack" //配置的地方就是這裏啦,至關於把npm的start命令指向webpack命令
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^1.12.9"
  }
}

npm的start是一個特殊的腳本名稱,它的特殊性表如今,在命令行中使用npm start就能夠執行相關命令,若是對應的此腳本名稱不是start,想要在命令行中運行時,須要這樣用npm run {script name}npm run buildjquery

Webpack的強大功能

生成Source Maps(使調試更容易)

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選項具備類似的缺點;

eval-source-map是一個很好的選項,不過記得只在開發階段使用它,繼續上面的例子,進行以下配置webpack

module.exports = {
  devtool: 'eval-source-map',//配置生成Source Maps,選擇合適的選項
  entry:  __dirname + "/app/main.js",
  output: {
    path: __dirname + "/public",
    filename: "bundle.js"
  }
}

使用webpack構建本地服務器

npm install --save-dev webpack-dev-server

devserver做爲webpack配置選項中的一項,具備如下配置選項web

devserver配置選項 功能描述
contentBase 默認webpack-dev-server會爲根文件夾提供本地服務器,若是想爲另一個目錄下的文件提供本地服務器,應該在這裏設置其所在目錄(本例設置到「public"目錄)
port 設置默認監聽端口,若是省略,默認爲」8080「
inline 設置爲true,當源文件改變時會自動刷新頁面
colors 設置爲true,使終端輸出的文件爲彩色的
historyApiFallback 在開發單頁應用時很是有用,它依賴於HTML5 history API,若是設置爲true,全部的跳轉將指向index.html

繼續把這些命令加到webpack的配置文件中正則表達式

module.exports = {
  devtool: 'eval-source-map',

  entry:  __dirname + "/app/main.js",
  output: {
    path: __dirname + "/public",
    filename: "bundle.js"
  },

  devServer: {
    contentBase: "./public",//本地服務器所加載的頁面所在的目錄
    colors: true,//終端中輸出結果爲彩色
    historyApiFallback: true,//不跳轉
    inline: true//實時刷新
  } 
}

Loaders

經過使用不一樣的loader,webpack經過調用外部的腳本或工具能夠對各類各樣的格式的文件進行處理,好比說分析JSON文件並把它轉換爲JavaScript文件,或者說把下一代的JS文件(ES6,ES7)轉換爲現代瀏覽器能夠識別的JS文件。npm

Loaders須要單獨安裝而且須要在webpack.config.js下的modules關鍵字下進行配置,Loaders的配置選項包括如下幾方面:json

  • test:一個匹配loaders所處理的文件的拓展名的正則表達式(必須)
  • loader:loader的名稱(必須)
  • include/exclude:手動添加必須處理的文件(文件夾)或屏蔽不須要處理的文件(文件夾)(可選);
  • query:爲loaders提供額外的設置選項(可選)
//安裝能夠裝換JSON的loader
npm install --save-dev json-loader
module.exports = {
  devtool: 'eval-source-map',

  entry:  __dirname + "/app/main.js",
  output: {
    path: __dirname + "/public",
    filename: "bundle.js"
  },

  module: {//在配置文件裏添加JSON loader
    loaders: [
      {
        test: /\.json$/,
        loader: "json"
      }
    ]
  },

  devServer: {
    contentBase: "./public",
    colors: true,
    historyApiFallback: true,
    inline: true
  }
}

Babel

  • 下一代的JavaScript標準(ES6,ES7),這些標準目前並未被當前的瀏覽器徹底的支持;
  • 使用基於JavaScript進行了拓展的語言,好比React的JSX

Babel實際上是幾個模塊化的包,其核心功能位於稱爲babel-core的npm包中,不過webpack把它們整合在一塊兒使用,可是對於每個你須要的功能或拓展,你都須要安裝單獨的包(用得最多的是解析Es6的babel-preset-es2015包和解析JSX的babel-preset-react包)。

// npm一次性安裝多個依賴模塊,模塊之間用空格隔開
npm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react
module.exports = {
  devtool: 'eval-source-map',

  entry:  __dirname + "/app/main.js",
  output: {
    path: __dirname + "/public",
    filename: "bundle.js"
  },

  module: {
    loaders: [
      {
        test: /\.json$/,
        loader: "json"
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel',//在webpack的module部分的loaders裏進行配置便可
        query: {
          presets: ['es2015','react']
        }
      }
    ]
  },

  devServer: {
    contentBase: "./public",
    colors: true,
    historyApiFallback: true,
    inline: true
  }
}

Babel的配置選項

 ".babelrc" 的配置文件,webpack會自動調用.babelrc裏的babel配置選項

//.babelrc
{
  "presets": ["react", "es2015"]
}

CSS

webpack提供兩個工具處理樣式表,css-loader 和 style-loader,兩者處理的任務不一樣,css-loader使你可以使用相似@import 和 url(...)的方法實現 require()的功能,style-loader將全部的計算後的樣式加入頁面中,兩者組合在一塊兒使你可以把樣式表嵌入webpack打包後的JS文件中。

//安裝
npm install --save-dev style-loader css-loader
//使用
module.exports = {
  devtool: 'eval-source-map',

  entry:  __dirname + "/app/main.js",
  output: {
    path: __dirname + "/build",
    filename: "bundle.js"
  },

  module: {
    loaders: [
      {
        test: /\.json$/,
        loader: "json"
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel'
      },
      {
        test: /\.css$/,
        loader: 'style!css'//添加對樣式表的處理
      }
    ]
  },

  devServer: {...}
}

注:感嘆號的做用在於使同一文件可以使用不一樣類型的loader

CSS module

module.exports = {
  devtool: 'eval-source-map',

  entry:  __dirname + "/app/main.js",
  output: {...},

  module: {
    loaders: [
      {
        test: /\.json$/,
        loader: "json"
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel'
      },
      {
        test: /\.css$/,
        loader: 'style!css?modules'//跟前面相比就在後面加上了?modules
      }
    ]
  },

  devServer: {...}
}

CSS預處理器

  • Less Loader
  • Sass Loader
  • Stylus Loader

首先安裝postcss-loader 和 autoprefixer(自動添加前綴的插件)

npm install --save-dev postcss-loader autoprefixer
//webpack配置文件
module.exports = {
  devtool: 'eval-source-map',
  entry: __dirname + "/app/main.js",
  output: {...},

  module: {
    loaders: [
      {
        test: /\.json$/,
        loader: "json"
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel'
      },
      {
        test: /\.css$/,
        loader: 'style!css?modules!postcss'
      }
    ]
  },

  postcss: [
    require('autoprefixer')//調用autoprefixer插件
  ],

  devServer: {...}
}

插件(Plugins)

使用插件的方法

要使用某個插件,咱們須要經過npm安裝它,而後要作的就是在webpack配置中的plugins關鍵字部分添加該插件的一個實例(plugins是一個數組)繼續看例子,咱們添加了一個實現版權聲明的插件。

//webpack.config.js
var webpack = require('webpack');

module.exports = {
  devtool: 'eval-source-map',
  entry:  __dirname + "/app/main.js",
  output: {...},

  module: {
    loaders: [
      { test: /\.json$/, loader: "json" },
      { test: /\.js$/, exclude: /node_modules/, loader: 'babel' },
      { test: /\.css$/, loader: 'style!css?modules!postcss' }//這裏添加PostCSS
    ]
  },
  postcss: [
    require('autoprefixer')
  ],

  plugins: [
    new webpack.BannerPlugin("Copyright Flying Unicorns inc.")//在這個數組中new一個就能夠了
  ],

  devServer: {...}
}

HtmlWebpackPlugin

這個插件的做用是依據一個簡單的模板,幫你生成最終的Html5文件,這個文件中自動引用了你打包後的JS文件。每次編譯都在文件名中插入一個不一樣的哈希值。

npm install --save-dev html-webpack-plugin

Hot Module Replacement

Hot Module Replacement(HMR)也是webpack裏頗有用的一個插件,它容許你在修改組件代碼後,自動刷新實時預覽修改後的效果。

//webpack中的配置
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  devtool: 'eval-source-map',
  entry: __dirname + "/app/main.js",
  output: {
    path: __dirname + "/build",
    filename: "bundle.js"
  },

  module: {
    loaders: [
      { test: /\.json$/, loader: "json" },
      { test: /\.js$/, exclude: /node_modules/, loader: 'babel' },
      { test: /\.css$/, loader: 'style!css?modules!postcss' }
    ]
  },
  postcss: [
    require('autoprefixer')
  ],

  plugins: [
    new HtmlWebpackPlugin({
      template: __dirname + "/app/index.tmpl.html"
    }),
    new webpack.HotModuleReplacementPlugin()//熱加載插件
  ],

  devServer: {
    colors: true,
    historyApiFallback: true,
    inline: true,
    hot: true
  }
}

安裝react-transform-hmr

npm install --save-dev babel-plugin-react-transform react-transform-hmr

配置Babel

{
  "presets": ["react", "es2015"],
  "env": {
    "development": {
    "plugins": [["react-transform", {
       "transforms": [{
         "transform": "react-transform-hmr",

         "imports": ["react"],

         "locals": ["module"]
       }]
     }]]
    }
  }
}

產品階段的構建

目前爲止,咱們已經使用webpack構建了一個完整的開發環境。可是在產品階段,可能還須要對打包的文件進行額外的處理,好比說優化,壓縮,緩存以及分離CSS和JS。

對於複雜的項目來講,須要複雜的配置,這時候分解配置文件爲多個小的文件可使得事情層次分明,以上面的例子來講,咱們建立一個「webpack.production.config.js」的文件,在裏面加上基本的配置,它和原始的webpack.config.js很像,以下

優化插件

  • OccurenceOrderPlugin :爲組件分配ID,經過這個插件webpack能夠分析和優先考慮使用最多的模塊,併爲它們分配最小的ID
  • UglifyJsPlugin:壓縮JS代碼;
  • ExtractTextPlugin:分離CSS和JS文件

咱們繼續用例子來看看如何添加它們,OccurenceOrder 和 UglifyJS plugins 都是內置插件,你須要作的只是安裝它們

npm install --save-dev extract-text-webpack-plugin
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  entry: __dirname + "/app/main.js",
  output: {
    path: __dirname + "/build",
    filename: "bundle.js"
  },

  module: {
    loaders: [
      {
        test: /\.json$/,
        loader: "json"
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel'
      },
      {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract('style', 'css?modules!postcss')
      }
    ]
  },
  postcss: [
    require('autoprefixer')
  ],

  plugins: [
    new HtmlWebpackPlugin({
      template: __dirname + "/app/index.tmpl.html"
    }),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.optimize.UglifyJsPlugin(),
    new ExtractTextPlugin("style.css")
  ]
}

緩存

webpack能夠把一個哈希值添加到打包的文件名中,使用方法以下,添加特殊的字符串混合體([name], [id] and [hash])到輸出文件名前

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  entry: __dirname + "/app/main.js",
  output: {
    path: __dirname + "/build",
    filename: "[name]-[hash].js"
  },

  module: {
    loaders: [
      {
        test: /\.json$/,
        loader: "json"
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel'
      },
      {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract('style', 'css?modules!postcss')
      }
    ]
  },
  postcss: [
    require('autoprefixer')
  ],

  plugins: [
    new HtmlWebpackPlugin({
      template: __dirname + "/app/index.tmpl.html"
    }),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.optimize.UglifyJsPlugin(),
    new ExtractTextPlugin("[name]-[hash].css")
  ]
}
var path = require('path');
var webpack = require('webpack');
/*
extract-text-webpack-plugin插件,
有了它就能夠將你的樣式提取到單獨的css文件裏,
不再用擔憂樣式會被打包到js文件裏了。
 */
var ExtractTextPlugin = require('extract-text-webpack-plugin');
/*
html-webpack-plugin插件,重中之重,webpack中生成HTML的插件,
具體能夠去這裏查看https://www.npmjs.com/package/html-webpack-plugin
 */
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: { //配置入口文件,有幾個寫幾個
        index: './src/js/page/index.js',
        list: './src/js/page/list.js',
        about: './src/js/page/about.js',
    },
    output: { 
        path: path.join(__dirname, 'dist'), //輸出目錄的配置,模板、樣式、腳本、圖片等資源的路徑配置都相對於它
        publicPath: '/dist/',               //模板、樣式、腳本、圖片等資源對應的server上的路徑
        filename: 'js/[name].js',           //每一個頁面對應的主js的生成配置
        chunkFilename: 'js/[id].chunk.js'   //chunk生成的配置
    },
    module: {
        loaders: [ //加載器,關於各個加載器的參數配置,可自行搜索之。
            {
                test: /\.css$/,
                //配置css的抽取器、加載器。'-loader'能夠省去
                loader: ExtractTextPlugin.extract('style-loader', 'css-loader') 
            }, {
                test: /\.less$/,
                //配置less的抽取器、加載器。中間!有必要解釋一下,
                //根據從右到左的順序依次調用less、css加載器,前一個的輸出是後一個的輸入
                //你也能夠開發本身的loader喲。有關loader的寫法可自行谷歌之。
                loader: ExtractTextPlugin.extract('css!less')
            }, {
                //html模板加載器,能夠處理引用的靜態資源,默認配置參數attrs=img:src,處理圖片的src引用的資源
                //好比你配置,attrs=img:src img:data-src就能夠一併處理data-src引用的資源了,就像下面這樣
                test: /\.html$/,
                loader: "html?attrs=img:src img:data-src"
            }, {
                //文件加載器,處理文件靜態資源
                test: /\.(woff|woff2|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
                loader: 'file-loader?name=./fonts/[name].[ext]'
            }, {
                //圖片加載器,雷同file-loader,更適合圖片,能夠將較小的圖片轉成base64,減小http請求
                //以下配置,將小於8192byte的圖片轉成base64碼
                test: /\.(png|jpg|gif)$/,
                loader: 'url-loader?limit=8192&name=./img/[hash].[ext]'
            }
        ]
    },
    plugins: [
        new webpack.ProvidePlugin({ //加載jq
            $: 'jquery'
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendors', // 將公共模塊提取,生成名爲`vendors`的chunk
            chunks: ['index','list','about'], //提取哪些模塊共有的部分
            minChunks: 3 // 提取至少3個模塊共有的部分
        }),
        new ExtractTextPlugin('css/[name].css'), //單獨使用link標籤加載css並設置路徑,相對於output配置中的publickPath

        //HtmlWebpackPlugin,模板生成相關的配置,每一個對於一個頁面的配置,有幾個寫幾個
        new HtmlWebpackPlugin({ //根據模板插入css/js等生成最終HTML
            favicon: './src/img/favicon.ico', //favicon路徑,經過webpack引入同時能夠生成hash值
            filename: './view/index.html', //生成的html存放路徑,相對於path
            template: './src/view/index.html', //html模板路徑
            inject: 'body', //js插入的位置,true/'head'/'body'/false
            hash: true, //爲靜態資源生成hash值
            chunks: ['vendors', 'index'],//須要引入的chunk,不配置就會引入全部頁面的資源
            minify: { //壓縮HTML文件    
                removeComments: true, //移除HTML中的註釋
                collapseWhitespace: false //刪除空白符與換行符
            }
        }),
        new HtmlWebpackPlugin({ //根據模板插入css/js等生成最終HTML
            favicon: './src/img/favicon.ico', //favicon路徑,經過webpack引入同時能夠生成hash值
            filename: './view/list.html', //生成的html存放路徑,相對於path
            template: './src/view/list.html', //html模板路徑
            inject: true, //js插入的位置,true/'head'/'body'/false
            hash: true, //爲靜態資源生成hash值
            chunks: ['vendors', 'list'],//須要引入的chunk,不配置就會引入全部頁面的資源
            minify: { //壓縮HTML文件    
                removeComments: true, //移除HTML中的註釋
                collapseWhitespace: false //刪除空白符與換行符
            }
        }),
        new HtmlWebpackPlugin({ //根據模板插入css/js等生成最終HTML
            favicon: './src/img/favicon.ico', //favicon路徑,經過webpack引入同時能夠生成hash值
            filename: './view/about.html', //生成的html存放路徑,相對於path
            template: './src/view/about.html', //html模板路徑
            inject: true, //js插入的位置,true/'head'/'body'/false
            hash: true, //爲靜態資源生成hash值
            chunks: ['vendors', 'about'],//須要引入的chunk,不配置就會引入全部頁面的資源
            minify: { //壓縮HTML文件    
                removeComments: true, //移除HTML中的註釋
                collapseWhitespace: false //刪除空白符與換行符
            }
        }),

        new webpack.HotModuleReplacementPlugin() //熱加載
    ],
    //使用webpack-dev-server,提升開發效率
    devServer: {
        contentBase: './',
        host: 'localhost',
        port: 9090, //默認8080
        inline: true, //能夠監控js變化
        hot: true, //熱啓動
    }
};

 

本文學習自:

入門Webpack,看這篇就夠了

相關文章
相關標籤/搜索