webpack使用小記

前言

webpack是目前前端開發必不可少的一款模塊加載器兼構建工具,它能極其方便的處理各類資源的打包和使用, 讓前端開發得到與後端開發幾乎一致的體驗。css

webpack特色

  • webpack 是以 commonJS 的形式來書寫腳本的,能夠直接使用 require或者import(es6寫法,配置babel支持) 的寫法來引入各模塊html

  • webpack除了支持編譯js爲模塊外,webpack也支持編譯html,css, js, less, jsx,圖片等很是多的資源爲模塊,只須要配置一下對應的加載器便可前端

  • webpack還能夠直接替代能替代很多本來屬於gulp的工做,好比打包,壓縮,混淆,圖片轉base64等node

  • webpack提供了配套的dev-server,而且支持熱更新(配置熱更新插件),無須本身用nodejs配置一個熱更新httpServer,開發調試很是便捷react

  • webpack支持自定義插件,能夠很容易的擴展特定的功能,好比目前如日中天的react,就有一款react-hot-loader插件來支持react項目的熱更新webpack

如何使用webpack

  • 在項目中安裝webpack
    npm install webpack --save-dev  
  • 在項目的根目錄新建一個 webpack.config.js 文件,加入各配置項git

  • 使用webpack命令行運行指令,好比 webpack --display-error-details,對項目進行編譯打包es6

webpack 2經常使用配置參數介紹

// file -> webpack.config
var webpackConfig = {
    // 須要編譯的入口文件配置
    entry: {
        index: './app/entry/index.js',    // index 指模塊的名稱,其餘配置項加入模塊時須要指定模塊名稱
        login: [ './app/entry/login.js' ],    // ./src/js/page/login.js 指的是該模塊的文件的路徑
        useinfo: [ './app/entry/userinfo.js', './app/entry/user.js' ]  // 能夠將二個文件合併做爲一個入口
    },
    
    // 編譯完的入口文件輸出配置
    output: {
        // 指定編譯模塊文件的存放目錄(/build/js/),不能用於html中的文件引用。
        path: path.resolve(__dirname, "build"), //如使用webpack-dev-server, 則該目錄的位置應設置爲爲虛擬web服務器的根目錄
        
        // 配置文件在html中引用的根路徑,會影響在html中模塊的引用路徑
        publicPath: "/assets/",
        //publicPath: "http://cdn.com/assets/",//你也能夠加上完整的url,效果與上面一致(不須要修改index.html中引用bundle.js的路徑,但發佈生產環境時,建議使用HtmlWebpackPlugin插件批量修改引用地址爲cdn地址)。
        
        // filename 指輸出的每一個js模塊名稱及存放路徑的定義,會影響在html中模塊的引用路徑
        filename: "js/bundle.js",  // 單頁應用只有一個入口文件時使用,在html頁面上經過<script src="/js/bundle.js"></script>引用入口模塊
        filename: "js/[name].js",  // 傳統多頁應用有多個入口文件時使用,[name] 代入entry配置中的任意一項模塊的名稱,例如:index, 在不一樣的頁面上引用不一樣的入口,例如在index.html頁面上經過<script src="/js/index.js"></script>引用入口模塊
        filename: "js/[hash]/[chunkhash].js",  // 爲生產環境實現前端靜態資源增量更新時使用,[hash]是根據每次編譯後項目整體文件的hash值, [chunkhash]是根據每一個模塊內容計算出的hash值。
        
    },
    
     // 模塊配置
     module: {
        // 模塊處理規則(包括配置模塊加載器,模塊編譯解析規則等等)
        rules: [
          // es6的js文件使用 babel-loader 來處理,轉換成es5
          {
            // 匹配的模塊文件範圍  
            test: /\.js$/,
            
            // 包括哪些範圍
            include: [
              path.resolve(__dirname, "app")
            ],
            
            // 排除哪些範圍
            exclude: [
              path.resolve(__dirname, "app/demo-files")
            ],
            
            // 使用多個插件,及指定插件配置
            use: [
                 // "babel-loader",         // 不指定插件配置的方式
                 {
                    loader: "babel-loader", // 指定插件配置的方式,注:babel的配置建議使用.babelrc來配置
                    options: {
                      presets: ["es2015"]
                    },
                 },
                 
                 // 如使用react-hot-loader,則須要在這裏加入
                 'react-hot-loader/webpack'
            ]
          },
    
          // 圖片文件使用 url-loader 來處理,小於8kb的直接轉爲base64
          {
              test: /\.(png|jpg|gif)$/,
              use: [
                  {
                      loader: 'url-loader',
                      options: {
                          limit: 8192,
                          // name 指輸出的每一個圖片模塊名稱的路徑定義
                          name: 'images/[name]-[chunkhash].[ext]',   //[name]指圖片文件名, [ext]指圖片的後綴名稱
                      },
                  },
              ],
          },
          
          // less文件使用style-loader, css-loader, less-loader來處理
          {
              test: /\.less$/,
              use: [
                  'style-loader',
                  'css-loader',
                  'less-loader',
                  extractTextPlugin.extract(['style','css', 'less'])     // 
              ],
          },
          
          // pcss文件使用style-loader, css-loader, postcss-loader來處理
          {
              test: /\.pcss$/,
              use: [
                  'style-loader',
                  'css-loader',
                  {
                      loader: 'postcss-loader',
                      options: {
                          plugins: function () {
                              return [
                                  require('postcss-import')(),      // 在@import css文件的時候讓webpack監聽並編譯
                                  require('precss'),                // 相似scss的語法,實際上若是隻是想用嵌套的話有cssnext就夠了
                                  require('postcss-cssnext'),       // cssnext可讓你寫CSS4的語言,並能配合autoprefixer進行瀏覽器兼容的不全,並且還支持嵌套語法
                              ];
                          },
                      },
                  },
              ],
          }
        ]
     },    
     
     // 配置如何訪問模塊
     resolve: {
         // 配置查找npm依賴包的路徑規則,默認是查找node_modules
         modules: [
          "node_modules",
          path.resolve(__dirname, "app")
        ],
        
        // 使用了哪些文件後綴名
        extensions: [".js", ".json", ".jsx", ".css"],
            
        // 模塊路徑的別名配置,將冗長的模塊引用路徑配置成簡短的模塊別名
        alias: {    
            "third": path.resolve(__dirname, "app/third"),              // 引用module,使用'third/module'
            "module": path.resolve(__dirname, "app/third/module.js"),   // 引用module,使用'module'
        }
     },
     
     // 性能配置
     performance: {
         // 當資源不符合性能規則時,以什麼方式進行提示, 默認值爲waring
         hints: "warning", // 輸出警告的方式,推薦在開發環境下使用
         hints: "error", // 輸出錯誤的方式,推薦在生產環境下使用
         hints: false, // 關閉提高
         
         maxAssetSize: 200000, // 單個資源容許的最大文件容量,單位:字節,默認250kb
         maxEntrypointSize: 400000, // 單個入口模塊引用的全部資源的最大文件容量,單位:字節,默認250kb
         
         // 控制哪些文件須要進行性能檢測,默認值以下
         assetFilter: function(assetFilename) {
              return !(/\.map$/.test(assetFilename))
         },
         // 控制只有css與js文件須要進行性能檢測
         assetFilter: function(assetFilename) { 
           // Function predicate that provides asset filenames
           return assetFilename.endsWith('.css') || assetFilename.endsWith('.js');
         }
     },
     
     // 經過增長輸出信息的方式爲瀏覽器開發者工具加強調試
     devtool: "source-map", // 爲模塊生成單獨的source-map文件,會大幅影響編譯速度
     devtool: "eval", // 不生成sourceMap, 可是命名模塊,編譯速度最快.
     devtool: "cheap-module-eval-source-map", // 開發環境推薦 
     devtool: "cheap-module-source-map", // 生產環境推薦 
     
     // 使用 cheap 模式能夠大幅提升 souremap 生成的效率。大部分狀況咱們調試並不關心列信息,並且就算 sourcemap 沒有列,有些瀏覽器引擎(例如 v8) 也會給出列信息。
     // 使用 eval 方式可大幅提升持續構建效率。官方文檔提供的速度對比表格能夠看到 eval 模式的編譯速度很快。
     // 使用 module 可支持 babel 這種預編譯工具(在 webpack 裏作爲 loader 使用)。
     // 使用 eval-source-map 模式能夠減小網絡請求。這種模式開啓 DataUrl 自己包含完整 sourcemap 信息,並不須要像 sourceURL 那樣,瀏覽器須要發送一個完整請求去獲取 sourcemap 文件,這會略微提升點效率。而生產環境中則不宜用 eval,這樣會讓文件變得極大。
     
     // 根路徑,默認值是__dirname,基於這個路徑去處理配置的模塊入口和加載器
     context: __dirname, // 默認值
     
     // 編譯環境,默認值是web
     target: "web", // 瀏覽器編譯環境
       
     // 將配置的模塊從bundle文件中分離出來,模塊能夠是 CommonJS, AMD, global and ES2015 modules 4種類型  
     externals: {
       react: 'react'
     },
       
     // 配置在編譯時輸出相關信息
     stats: { //object
         assets: true,
         colors: true,
         errors: true,
         errorDetails: true,
         hash: true,
         // ...
    },
      
     // 配置開發服務器
     // 要使之生效,還須要同時在entry的每一項以前加入'webpack-dev-server/client?http://{指定的IP}:{指定的端口}', 
     // 'webpack/hot/log-apply-result'與'webpack/hot/only-dev-server'
     // 如使用了react-hot-loader, 則還須要加入'react-hot-loader/patch'
     devServer: {
         // 配置代理服務器
         proxy: { 
           '/api': 'http://localhost:3000' // 訪問路由/api,會轉發到localhost:3000的地址去
         },
         contentBase: [ path.resolve(__dirname, "build"), path.resolve(__dirname, "mock") ], //  靜態資源路徑,須要配置編譯後的模塊文件存放的路徑(同output中的path),也能夠在這裏配置其餘的,好比mock文件存放的路徑
         compress: true, // 是否開啓壓縮
         historyApiFallback: true, // true for index.html upon 404, object for multiple paths
         hot: true, // 是否開啓熱更新,須要配置HotModuleReplacementPlugin
         https: false, // 是否使用https
         noInfo: true, // 在熱更新時,只會輸出錯誤與警告信息,不會輸出其餘日誌
         stats: "verbose" // 輸出全部日誌
     },    
     
     // 配置插件(未完待續)
     plugins: [
         new webpack.EnvironmentPlugin(['NODE_ENV']),  // 能夠隨意指定前端node環境
         new webpack.DefinePlugin({
           'process.env': {NODE_ENV: JSON.stringify(process.env.NODE_ENV)}   // 能夠隨意指定前端node環境
         }),    
         new extractTextPlugin("css/[name].css"),       // css抽取,須要引入模塊extract-text-webpack-plugin,而且須要在模塊加載器處也加入對應配置
         new HtmlWebpackPlugin({                        // html插件,定義html模板,生成html文件,並將指定的模塊插入html中(須要引入模塊html-webpack-plugin)
             template: path.join('src/', 'template.html'),  // 模板html文件的存放位置
             filename: path.join('build/', 'index.html'),   // 指輸出的每一個html文件名稱及存放路徑的定義
             inject: 'body',                                // 表示插入至body標籤內
             chunks: [      // 插入的模塊在html上會自動使用publicPath與模塊的filename做爲引用路徑
                index       // 插入index入口模塊,也能夠插入其餘入口模塊或者公共模塊(好比使用CommonsChunkPlugin提取的common模塊)
             ],
         }),
         // 提供公共代碼
         new webpack.optimize.CommonsChunkPlugin('common.js'), // 默認會把全部入口節點的公共代碼提取出來,生成一個common.js
         new webpack.optimize.CommonsChunkPlugin('common.js',['main','index']), // 默認會把全部入口節點的公共代碼提取出來,生成一個common.js, 只提取main節點和index節點
         new webpack.optimize.CommonsChunkPlugin({          // 有選擇性的提取(對象方式傳參)
             name: "common",                                // name能夠是作生意模塊名(common是公共模塊名)注意不要.js後綴
             filename: "js/[name].js",                      // 指定輸出的js文件名稱及路徑   
             chunks: ['main','user','index'],               // 將指定的入口模塊提取出來
             minChunks: 2                                   // 公共模塊被使用的最小次數。好比配置爲2,也就是同一個模塊只有被2個之外的頁面同時引用時纔會被提取出來做爲common chunks。
         }),
         new webpack.optimize.CommonsChunkPlugin({          // 有選擇性的提取(對象方式傳參)
              name: "index",                                // name能夠是任意模塊名,注意不要.js後綴
              filename: "js/[name].js",                     // 指定輸出的js文件名稱及路徑 
          }),
         new webpack.HotModuleReplacementPlugin(),  // 熱更新插件,使用dev-server必備
         new webpack.NoEmitOnErrorsPlugin(),        // 在webpack 2中使用NoErrorsPlugin會有警告提示
         new webpack.ProgressPlugin(function(percentage, msg) {
             logUpdate(percentage * 100 + '%', msg);  // 實時更新編譯進度,須要同時使用實時更新日誌模塊log-update
         }),
         new webpack.optimize.UglifyJsPlugin({        // 解析/壓縮/美化全部的js模塊,若有須要,這裏能夠經過配置except能夠防止變量被改變
             mangle: {
                 except: ['$super', '$', 'exports', 'require']
             }
         }),
         
         // 自定義插件函數,函數會接受到webpack的編譯對象compiler,用this一樣也能獲取到
         function(compiler) {
             this.plugin("done", function(stats) {  //使用.plugin api增長自定義插件,'done'表示觸發時機爲編譯結束後,stats表示編譯生成的模塊的詳細信息
                 require("fs").writeFileSync(path.join(__dirname, "stats.generated.json"), JSON.stringify(stats.toJson()));
                 require("open")(('http://localhost:9090/index.html')); // 還能夠在編譯完成後控制自動喚起瀏覽器並打開項目的入口頁面(須要安裝open模塊)
             });
         },
     ],
};

module.exports = webpackConfig;

  

webpack 啓動 devServer

var webpackConfig = require('./webpack.config');  // 獲取webpack配置
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var devServerOptions = {
    // 配置代理服務器
     proxy: { 
       '/api': 'http://localhost:3000' // 訪問路由/api,會轉發到localhost:3000的地址去
     },
     contentBase: [ path.resolve(__dirname, "build"), path.resolve(__dirname, "mock") ], //  靜態資源路徑,須要配置編譯後的模塊文件存放的路徑(同output中的path),也能夠在這裏配置其餘的,好比mock文件存放的路徑
     compress: true, // 是否開啓壓縮
     historyApiFallback: true, // true for index.html upon 404, object for multiple paths
     hot: true, // 是否開啓熱更新,須要配置HotModuleReplacementPlugin
     https: false, // 是否使用https
     noInfo: true, // 在熱更新時,只會輸出錯誤與警告信息,不會輸出其餘日誌
     stats: "verbose" // 輸出全部日誌
};

var compiler = webpack(webpackConfig);
var webpackDevServer = new WebpackDevServer(compiler, devServerOptions);
webpackDevServer.listen('9090', 'http://localhost', function (err) {
    if (err) {
        console.error(err);
    }
});
相關文章
相關標籤/搜索