WebPack常用功能介紹

jopen 8年前發布 | 360K 次閱讀 前端技術 webpack

WebPack常用功能介紹

概述

Webpack是一款用戶打包前端模塊的工具。主要是用來打包在瀏覽器端使用的javascript的。同時也能轉換、捆綁、打包其他的靜態資源,包括css、image、font file、template等。個人認為它的優點就是易用,而且常用功能基本都有,另外可以通過自己開發loader和plugin來滿足自己的需求。這里就盡量詳細的來介紹下一些基本功能的使用。

安裝

npm install webpack

運行webpack

webpack需要編寫一個config文件,然后根據這個文件來執行需要的打包功能。我們現在來編寫一個最簡單的config。新建一個文件,命名為webpack-config.js。config文件實際上就是一個Commonjs的模塊。內容如下:

var webpack = require('webpack');
var path = require('path');
var buildPath = path.resolve(dirname,"build");
var nodemodulesPath = path.resolve(dirname,'node_modules');

var config = { //入口文件配置 entry:path.resolve(__dirname,'src/main.js'), resolve:{ extentions:["","js"]//當requrie的模塊找不到時,添加這些后綴 }, //文件導出的配置 output:{ path:buildPath, filename:"app.js" } }

module.exports = config;</pre>

我的目錄結構是這樣的:

webpack
    |---index.html
    |---webpack-config.js
    |---src
         |---main.js
         |---js
              |---a.js

main.js文件內容如下:

var a = require('./js/a');
a();
console.log('hello world');
document.getElementById("container").innerHTML = "<p>hello world</p>";

a.js文件內容如下:

module.exports = function(){
    console.log('it is a ');
}

然后我們執行如下的命令:

webpack --config webpack-config.js --colors

這樣我們就能在目錄里面看到一個新生成的目錄build,目錄結構如下:

webpack
    |---index.html
    |---webpack-config.js
    |---build
         |---app.js

然后引用app.js就Ok啦。main.js和模塊a.js的內容就都打包到app.js中了。這就演示了一個最簡單的把模塊的js打包到一個文件的過程了。

介紹webpack config文件

webpack是根據config里面描述的內容對一個項目進行打包的。接著我們來解釋下config文件中的節點分別代表什么意思。一個config文件,基本都是由以下幾個配置項組成的。

  • entry

    </li> </ul>

    配置要打包的文件的入口;可以配置多個入口文件,下面會有介紹。

    • resolve

      配置文件后綴名,除了js,還有jsx、coffee等等。除了這個功能還可以配置其他有用的功能,由于我還不完全了解,有知道的朋友歡迎指教。

      </li>

    • output

      配置輸出文件的路徑,文件名等。

      </li>

    • module(loaders)

      </li> </ul>

      配置要使用的loader。對文件進行一些相應的處理。比如babel-loader可以把es6的文件轉換成es5。大部分的對文件的處理的功能都是通過loader實現的。loader就相當于gulp里的task。loader可以用來處理在入口文件中require的和其他方式引用進來的文件。loader一般是一個獨立的node模塊,要單獨安裝。

      loader配置項:

      test: /\.(js|jsx)$/,//注意是正則表達式,不要加引號,匹配要處理的文件
          loader: 'eslint-loader',//要使用的loader,"-loader"可以省略
          include: [path.resolve(__dirname, "src/app")],//把要處理的目錄包括進來
          exclude: [nodeModulesPath]//排除不處理的目錄

      目前已有的loader列表:

      https://webpack.github.io/docs/list-of-loaders.html </div>

      一個module的例子:

      module: {
          preLoaders: [
            {
              test: /\.(js|jsx)$/,
              loader: 'eslint-loader',
              include: [path.resolve(__dirname, "src/app")],
              exclude: [nodeModulesPath]
            },
          ],
          loaders: [
            {
              test: /\.(js|jsx)$/, //正則表達式匹配 .js 和 .jsx 文件
              loader: 'babel-loader?optional=runtime&stage=0',//對匹配的文件進行處理的loader 
              exclude: [nodeModulesPath]//排除node module中的文件
            }
          ]
      }

      • plugins

        顧名思義,就是配置要使用的插件。不過plugin和loader有什么差別還有待研究。

        </li> </ul>

        來看一個使用plugin的例子:

        plugins: [
            //壓縮打包的文件
            new webpack.optimize.UglifyJsPlugin({
              compress: {
                //supresses warnings, usually from module minification
                warnings: false
              }
            }),
            //允許錯誤不打斷程序
            new webpack.NoErrorsPlugin(),
            //把指定文件夾xia的文件復制到指定的目錄
            new TransferWebpackPlugin([
              {from: 'www'}
            ], path.resolve(__dirname,"src"))
          ]

        目前已有的plugins列表:

        http://webpack.github.io/docs/list-of-plugins.html </div>

        如何壓縮輸出的文件

        plugins: [
            //壓縮打包的文件
            new webpack.optimize.UglifyJsPlugin({
              compress: {
                //supresses warnings, usually from module minification
                warnings: false
              }
            })]

        如何copy目錄下的文件到輸出目錄

        copy文件需要通過插件"transfer-webpack-plugin"來完成。

        安裝:

        npm install transfer-webpack-plugin  -save

        配置:

        var TransferWebpackPlugin = require('transfer-webpack-plugin');
        //其他節點省略    
        plugins: [
            //把指定文件夾下的文件復制到指定的目錄
            new TransferWebpackPlugin([
              {from: 'www'}
            ], path.resolve(__dirname,"src"))
          ]

        打包javascript模塊

        支持的js模塊化方案包括:

        • ES6 模塊

          import MyModule from './MyModule.js';

          </li>

        • CommonJS

          var MyModule = require('./MyModule.js');

          </li>

        • AMD

          define(['./MyModule.js'], function (MyModule) {});

          </li> </ul>

          上面已經演示了打包js模塊,這里不再重復。ES6的模塊需要配置babel-loader來先把處理一下js文件。下面展示下打包ES模塊的配置文件:

          var webpack = require('webpack');
          var path = require('path');
          var buildPath = path.resolve(dirname, 'build');
          var nodeModulesPath = path.resolve(dirname, 'node_modules');
          var TransferWebpackPlugin = require('transfer-webpack-plugin');

          var config = { entry: [path.join(dirname, 'src/main.js')], resolve: { extensions: ["", ".js", ".jsx"] //node_modules: ["web_modules", "node_modules"] (Default Settings) }, output: { path: buildPath,
          filename: 'app.js'
          }, plugins: [ new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }), new webpack.NoErrorsPlugin(), new TransferWebpackPlugin([ {from: 'www'} ], path.resolve(
          dirname,"src")) ], module: { preLoaders: [ { test: /.(js|jsx)$/, loader: 'eslint-loader', include: [path.resolve(__dirname, "src/app")], exclude: [nodeModulesPath] }, ], loaders: [ { test: /.js$/, //注意是正則表達式,不要加引號 loader: 'babel-loader?optional=runtime&stage=0',//babel模塊相關的功能請自查,這里不做介紹 exclude: [nodeModulesPath] } ] }, //Eslint config eslint: { configFile: '.eslintrc' //Rules for eslint }, };

          module.exports = config;</pre>

          打包靜態資源

          • css/sass/less

            </li> </ul>

            安裝css-loader和style-loader

            npm install css-loader --save -dev
            npm install style-loader --save -dev

            config配置:

            var config = {
                entry:path.resolve(__dirname,'src/main.js'),
                resolve:{
                    extentions:["","js"]
                },
                output:{
                    path:buildPath,
                    filename:"app.js"
                },
                module:{
                    loaders:[{
                        test:/\.css$/,
                        loader:'style!css',
                        exclude:nodemodulesPath
                    }]
                }
            }

            style-loader會把css文件嵌入到html的style標簽里,css-loader會把css按字符串導出,這兩個基本都是組合使用的。打包完成的文件,引用執行后,會發現css的內容都插入到了head里的一個style標簽里。如果是sass或less配置方式與上面類似。

            • images

              </li> </ul>

              可以通過url-loader把較小的圖片轉換成base64的字符串內嵌在生成的文件里。安裝:

              npm install url-loader --save -dev

              config配置:

              var config = {
                  entry:path.resolve(__dirname,'src/main.js'),
                  resolve:{
                      extentions:["","js"]
                  },
                  output:{
                      path:buildPath,
                      filename:"app.js"
                  },
                  module:{
                      loaders:[{
                          test:/\.css$/,
                          loader:'style!css',//
                          exclude:nodemodulesPath
                      },
                      { test:/\.png$/,loader:'url-loader?limit=10000'}//限制大小小于10k的
                      ]
                  }
              }

              css文件內容:

              #container{
                  color: #f00;
                  background:url(images/logo-201305.png);
                  /*生成完圖片會被處理成base64的字符串 注意:不要寫'/images/logo-201305.png',否則圖片不被處理*/
              }

              • iconfont

                </li> </ul>

                內嵌iconfont的使用方法其實和上述處理png圖片的方法一致。通過url-loader來處理。

                config配置:

                var config = {
                    entry:path.resolve(__dirname,'src/main.js'),
                    resolve:{
                        extentions:["","js"]
                    },
                    output:{
                        path:buildPath,
                        filename:"app.js"
                    },
                    module:{
                        loaders:[{
                            test:/\.css$/,
                            loader:'style!css',//
                            exclude:nodemodulesPath
                        },
                        { test:/\.(png|woff|svg|ttf|eot)$/,loader:'url-loader?limit=10000'}//限制大小小于10k的
                        ]
                    }
                }

                css文件內容:

                @font-face {font-family: 'iconfont';
                src: url('fonts/iconfont.eot'); /* IE9*/
                src: url('fonts/iconfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
                url('fonts/iconfont.woff') format('woff'), /* chrome、firefox */
                url('fonts/iconfont.ttf') format('truetype'), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/
                url('fonts/iconfont.svg#iconfont') format('svg'); /* iOS 4.1- */
                }

                執行打包后會把字體文件都轉換成base64字符串內容到文件里.這里有個頭疼的問題,就是每個瀏覽器支持的字體格式不一樣,由于把全部格式的字體打包進去,造成不必要的資源浪費。

                打包template

                我一大包handlebars的模塊為例,來演示下打包模塊的過程。有的模板對應的loader,有可能沒有現車的,恐怕要自己實現loader。

                先安裝必須的node模塊

                npm install handlebars-loader --save -dev
                npm install handlebars -save//是必須的

                config配置:

                var config = {
                    entry:path.resolve(__dirname,'src/main.js'),
                    resolve:{
                        extentions:["","js"]
                    },
                    output:{
                        path:buildPath,
                        filename:"app.js"
                    },
                    module:{
                        loaders:[
                        { test: /\.html$/, loader: "handlebars-loader" }
                        ]
                    }
                }

                新建一個模板文件tb.html,目錄結構:

                webpack
                    |---index.html
                    |---webpack-config.js
                    |---src
                         |---template
                         |         |---tb.html
                         |---main.js

                main.js中調用模塊的代碼如下:

                var template = require("./template/tp.html");
                var data={say_hello:"it is handlebars"};
                var html = template(data);
                document.getElementById('tmpl_container').innerHTML = html;

                公用的模塊分開打包

                這需要通過插件“CommonsChunkPlugin”來實現。這個插件不需要安裝,因為webpack已經把他包含進去了。接著我們來看配置文件:

                var config = {
                    entry:{app:path.resolve(__dirname,'src/main.js'),
                            vendor: ["./src/js/common"]},//【1】注意這里
                    resolve:{
                        extentions:["","js"]
                    },
                    output:{
                        path:buildPath,
                        filename:"app.js"
                    },
                    module:{
                        loaders:[{
                            test:/\.css$/,
                            loader:'style!css',
                            exclude:nodemodulesPath
                        }
                        ]
                    },
                    plugins:[
                        new webpack.optimize.UglifyJsPlugin({
                             compress: {
                                warnings: false
                             }
                        }),
                        //【2】注意這里  這兩個地方市用來配置common.js模塊單獨打包的
                        new webpack.optimize.CommonsChunkPlugin({
                            name: "vendor",//和上面配置的入口對應
                            filename: "vendor.js"http://導出的文件的名稱
                        })
                    ]
                }

                目錄結構現在是這樣的:

                webpack
                  |---index.html
                  |---webpack-config.js
                  |---src
                     |---main.js
                     |---js
                          |---a.js    //a里面require了common
                          |---common.js

                執行webpack會生成app.js和common.js兩個文件.

                多個入口

                config配置:

                var config = {    
                    entry:{
                        m1:path.resolve(__dirname,'src/main.js'),
                         m2:path.resolve(__dirname,'src/main1.js')
                    },//注意在這里添加文件的入口
                    resolve:{
                        extentions:["","js"]
                    },
                    output:{
                        path:buildPath,
                        filename:"[name].js"http://注意這里使用了name變量
                    }    
                }

                webpack-dev-server

                在開發的過程中個,我們肯定不希望,每次修改完都手動執行webpack命令來調試程序。所以我們可以用webpack-dev-server這個模塊來取代煩人的執行命令。它會監聽文件,在文件修改后,自動編譯、刷新瀏覽器的頁面。另外,編譯的結果是保存在內存中的,而不是實體的文件,所以是看不到的,因為這樣會編譯的更快。它就想到與一個輕量的express服務器。安裝:

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

                config配置:

                var config = {
                    entry:path.resolve(__dirname,'src/main.js'),
                    resolve:{
                        extentions:["","js"]
                    },
                    //Server Configuration options
                    devServer:{
                        contentBase: '',  //靜態資源的目錄 相對路徑,相對于當前路徑 默認為當前config所在的目錄
                        devtool: 'eval',
                        hot: true,        //自動刷新
                        inline: true,    
                        port: 3005        
                    },
                    devtool: 'eval',
                    output:{
                        path:buildPath,
                        filename:"app.js"
                    },
                    plugins: [
                        new webpack.HotModuleReplacementPlugin(),//這個好像也是必須的,雖然我還沒搞懂它的作用
                        new webpack.NoErrorsPlugin()
                    ]
                }

                我的目錄結構:

                webpack
                  |---index.html
                  |---webpack-config.js//我把靜態資源目錄配置在了這里
                  |---src
                     |---main.js
                     |---js
                          |---a.js
                          |---common.js

                執行命令:

                webpack-dev-server --config webpack-dev-config.js  --inline --colors

                默認訪問地址: http://localhost :3000/index.html(根據配置會不一樣)

                有一點需要聲明,在index.html(引用導出結果的html文件)里直接引用“app.js”,不要加父級目錄,因為此時app.js在內存里與output配置的目錄無關:

                <script type="text/javascript" src="app.js"></script>
                 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
                 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
                 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!