webpack2教程--從入門到放棄

開車以前,先介紹一些npm的命令:

:D
進入D盤javascript

mkdir webappcss

建立webapp文件夾

cd webapphtml

進入webapp文件夾

mkdir webapp && cd webappvue

以上兩步建立和進入文件夾能夠合併爲一步

npm init -yjava

快速生成package.json文件

npm install xxx --save-devnode

//安裝模塊並加入到開發依賴中,好比webpack

npm install xxx --savejquery

安裝模塊並加入到生產依賴中,好比Jquery

npm install xxx@2.3.0webpack

下載指定版本

npm view webpack versions --jsongit

若是忘記版本號,能夠列出全部版本號

npm install -g cnpm --registry=https://registry.npm.taobao.orges6

下載淘寶鏡像源,國內npm下載很慢,並且有些包下下來貌似會有問題,好比node-sass。

下載以後就能夠直接使用了,使用方式跟Npm同樣,只不過是改爲cnpm

cls

清空命令提示符窗口內容




webpack

1. html篇

介紹完npm基本的東西后,下面開始擼webpack

有關webpack的基本概念建議到官網查看,解釋的更爲清楚,下面只簡單介紹。

1.  在根目錄下生成package.json文件: npm init -y


2.  安裝webapck cnpm install webpack --save-dev


3. 建立webpack.config.js文件: echo > webpack.config.js
var path=require("path");
module.exports={
   <!--  要打包的文件 -->
    entry:"./index.js",

    output:{
        <!-- 指定打包後的文件名字 -->
        filename:"bundle.js",
        <!-- 打包後的文件路徑 -->
        path:path.resolve(__dirname,"dist")
    }
}
4.建立src目錄,並在src目錄下建立index.html, index.js文件並隨便輸一點東西
window.onload=function(){
         alert(1)
    }
5.執行 webpack 命令,能夠發現webpack幫咱們在dist下生成了一個main.js文件,打開main.js並拖到最下面你會發現index.js的內容就在裏面。

打包完以後,咱們在dist生成了js文件,可是咱們的index.html在src下面,你能夠手動的複製src下的html文件到dist目錄下,而且將打包後的js文件引入。不過像咱們這麼懶的人,仍是但願webpack可以幫咱們在dist下也生成index.html,要是能自動引入打包後的js文件,那就再好不過了。這時候,是時候來一發插件了。


6.cnpm install html-webpack-plugin --save-dev
修改webpack.config.js
var HtmlWebpackPlugin = require('html-webpack-plugin');
var path = require("path")
module.exports = {
    entry:"./index.js",
    output: {
        path: path.resolve(__dirname, 'dist'),
         filename:"bundle.js",
    },
    plugins: [new HtmlWebpackPlugin({
        title: "測試"       
    })]
};
從新執行命令 webpack ,你會發如今dist下多生成了一個index.html文件,打開發現還有一個script的標籤引用着咱們打包後的文件,nice。

不過問題又來了,html文件很簡陋,就是emmet幫咱們生成的Html5文件,你可能但願還帶有更多的 meta標籤,像這樣的
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta name="format-detection" content="telephone=no, email=no"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
</head>
<body>
    <header></header>
    <nav></nav>
    <div id="app"></div>
    <footer></footer>
</body>
此時,你能夠本身寫一個模板,只須要告訴html-webpack-plugin插件文件的位置就能夠了。
修改webpack.config.js
plugins: [
    new htmlWebpackPlugin({
        title:"首頁",
        <!-- 指定模板位置 -->
        template:'./src/index.html',
        <!-- 指定打包後的文件名字 -->
        filename: 'index.html'
    })
]
對於多疑症的你,打包屢次後你可能會懷疑文件修改生效了沒有,此時你能夠安裝clean-webpack-plugin插件,在每次打包時,先刪除原來的dist目錄,再從新打包,這樣就能夠放心的睡覺,不用擔憂門沒關了。
7.cnpm install clean-webpack-plugin --save-dev
plugins:[
    new htmlWebpackPlugin({
        title:"首頁",
        template:'./src/index.html',
        filename: 'index.html'
    }),
    <!-- 每次打包前先刪除dist目錄 -->
    new CleanWebpackPlugin(['dist'])
]

css篇


以往咱們寫css都是寫好後手動經過link引入到html,使用webpack後,你將再也不須要手動作這些操做,只須要在js文件中引入,webpack就能幫你搞定,不過須要一些loader和plugin的支持。

cnpm install --save-dev css-loade style-loader

修改webpack.config.js
###爲了處理css文件咱們須要多配置一個module參數,並使用css-loader來將css文件打包到成「字符串」到js文件中,並使用style-loader將打包後的字符串提取出來並append<style>標籤到head下面 

var path=require("path");
var htmlWebpackPlugin=require('html-webpack-plugin');
var CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports={
  entry:{
    main:'./src/index.js'
  },
  output:{
    filename:"bundle.js",
    path:path.resolve(__dirname,'dist')
  },
  module:{
    rules:[   
        <!-- test檢測到以xxx結尾的東西use對應的loader -->
        {
            test: /\.css$/,
            use: [ 'style-loader', 'css-loader' ]         
        }
    ]
  },
  plugins:[
    new htmlWebpackPlugin({
      title:"首頁",
      template:'./src/index.html',
      filename:"index.html"
    }),
    new CleanWebpackPlugin(['dist'])    
  ]
}
哦,據說你想用sass 預處理 器,那麼只須要在use里加多一個sass-loader,並安裝依賴
cnpm install --save-dev sass-loader node-sass

rules:[  
    {
        test: /\.scss$/,
        use: [ 'style-loader', 'css-loader',"sass-loader" ]         
    }
]
什麼,想要自動補全瀏覽器後綴autoprefixer?沒問題
cnpm install --save-dev  postcss-loader

rules:[  
        {
            test: /\.s?css$/,
            use: [
                    {
                        loader: "style-loader"
                    }, 
                    {
                        loader: "css-loader"
                    }, 
                    {
                        loader: 'postcss-loader',
                        options: {
                            plugins:  [     
                                 require('autoprefixer')({
                                  browsers: ['last 10 versions']
                              })
                            ]
                        }
                    },
                    {
                        loader: "sass-loader"
                    }
                ]         
        }
    ]

這裏須要注意,use裏面的執行順序是倒序的 ,,webpack會以倒敘的方式處理並將處理後的結果返回給上一個loader,最後經過style-loader將文件的內容append到head下面的style標籤裏。

教練,我還想要自動刷新

當你修改一點文件後,你須要重執行命令新編譯文件,而後刷新頁面。若是你使用過gulp的自動刷新好比live-reload,那你也必定但願webpack也有一樣的功能,webpack-dev-server知足你的需求而且可以給你更多。

安裝webpack-dev-server到開發依賴  cnpm install --save-dev webpack-dev-server
<!-- 在package.json中加入: -->
"scripts": {
    "dev": "webpack-dev-server"
}
經過npm run dev便可執行建立一個服務器,打開localhsot:8080
此時再修改文件,你會發現頁面自動刷新了而且修改生效了,不過你看不到從新編譯後的文件在哪裏,應爲webpack-dev-server將文件編譯到了內存中 ,比起從新生成文件效率會更高,固然只適用於開發階段。
啓動服務後,若是你 還想讓他本身 打開Localhost,還想 使用模塊熱重載 ,能夠加多一個配置
devServer:{
         open:true,  
         hot: true,// 告訴 dev-server咱們想用HMR模式                   
  }
開發的時候咱們並不在乎 style這種形式,可是咱們但願在生產環境下 css能從js文件宏分離出來,咱們但願能css能跟js並行加載,並且能夠避免由於Js文件過大,加載慢而產生的flash of unstyle(無樣式頁面閃爍)。
使用「extract-text-webpack-plugin」插件來分離css代碼。

修改webpack.config.js

cnpm install --save-dev  extract-text-webpack-plugin
var path=require("path");
var webpack=require('webpack');
var htmlWebpackPlugin=require('html-webpack-plugin');
var CleanWebpackPlugin = require('clean-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");

var extractSass = new ExtractTextPlugin({
    filename: "[name].[contenthash].css",
    disable: process.env.NODE_ENV === "development"
});

//經過設置環境變量來告訴webpack咱們在development模式下不須要提取css到單獨在文件,只有當不是development下(也便是production)才須要提取文件。

module.exports={
  entry:{
    main:'./src/index.js'
  },
  output:{
    filename:"bundle.js",
    path:path.resolve(__dirname,'dist')
  },
  devServer:{
         open:true,  
         hot: true, <!-- 告訴 dev-server咱們想用HMR模式 -->                
  },
  module:{
    rules:[
        {
        test: /\.s?css$/,
              use: extractSass.extract({

                  use: [
                  {
                      loader: "css-loader"
                  }, 
                  {
                    loader: 'postcss-loader',
                    options: {
                      plugins:  [     
                        require('autoprefixer')
                      ]
                    }
                  },
                  {
                      loader: "sass-loader"
                  }],
                  fallback: "style-loader"
              })
          }
    ]
  },
  plugins:[
    <!-- 使用此插件來支持熱重載 -->
    new webpack.HotModuleReplacementPlugin(),

    new htmlWebpackPlugin({
      title:"首頁",
      template:'./src/index.html',
      filename:"index.html"
    }),
    new CleanWebpackPlugin(['dist']),
    extractSass
  
  ]
}

修改package.json ,本人爲window10系統

"scripts": {
    "dev": "set NODE_ENV=development&&webpack-dev-server",
    "build":"webpack -p"
}
分別執行npm run dev以及npm run build,你會發先npm run build時css文件被提取到一個單獨的文件了。


js篇

--------------------------------好累啊下面直接上代碼了

爲了使用promise,async等es6,7語法,同時兼容低版本瀏覽器,你還須要將js轉碼爲es5。

你須要安裝如下依賴包
cnpm install --save-dev

    "babel-core": "^6.25.0",
    "babel-loader": "^7.0.0",
    "babel-plugin-transform-object-rest-spread": "^6.23.0",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-env": "^1.5.2",

在module下增長:
{
    test: /\.js$/,
    exclude: /node_modules/,
    use: {
        loader: 'babel-loader',
        options: {
            presets: ['env'],
            plugins: ['transform-runtime']
        }
    }
}

寫一點async或者prmise代碼,打包後發現promise變成了_promise2


代理



先後端分離開發時常常還會遇到跨域的問題,還能夠利用devServer來進行代理

devServer:{
    open:true,  
    hot: true, 
    proxy: {
        '/api/': {
            target: 'http://baidu.com',
            secure: false,
            changeOrigin: true
        }
    }

$.ajax({
    url:'/api/',
    success:function(res){
        console.log(res)
    },
    error:function(res){
        console.log(res)
    }
})

圖片,字體篇

{
    test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
    loader: 'url-loader',
    query: {
        limit: 8000,
        <!-- 小於8k的轉化爲Base64 -->
        name: '[name].[hash:7].[ext]'
    }
}, 

{
    test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
    loader: 'url-loader',
    query: {
        limit: 8000,
         name: 'font/[name].[hash:7].[ext]'
    }
}
你可能想要把全部img或者font文件分別放到一個img或者font文件夾下,能夠這麼寫:name: 'img/[name].[hash:7].[ext]'


若是你不想下載字體文件下來,可已上傳到阿里字體庫並使用阿里的在線字體圖標,並複製本身的文件的在線地址。


在css裏面像這麼用:@import url("//at.alicdn.com/t/font_s0zqwb6by3lhm2t9.css");

打包多文件

var path=require("path");
var webpack=require('webpack');
var htmlWebpackPlugin=require('html-webpack-plugin');
var CleanWebpackPlugin = require('clean-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");

var extractSass = new ExtractTextPlugin({
    filename: "[name].[contenthash].css",
    disable: process.env.NODE_ENV === "development"
});

module.exports={
  entry:{
    "main":'./src/js/index.js',
    "car":"./src/js/car.js",
    "goods":"./src/js/goods.js"
  }, 
 
  output:{
    filename:"[name].[hash].js",
    path:path.resolve(__dirname,'dist')
  },
 
  devServer:{
        open:true,  
        hot: true,
        proxy: {
            '/api/': {
                target: 'http://baidu.com',
                secure: false,
                changeOrigin: true
            }
        }
        
  },

  module:{
    rules:[
    
      {
        test: /\.s?css$/,
              use: extractSass.extract({
                  use: [
                  {
                      loader: "css-loader"
                  }, 
                  {
                    loader: 'postcss-loader',
                    options: {
                        plugins:  [     
                            require('autoprefixer')({
                              browsers: ['last 10 versions']
                          })
                        ]
                    }
                  },
                  {
                      loader: "sass-loader"
                  }],
                  fallback: "style-loader"
              })
          },
          {
              test: /\.js$/,
              exclude: /node_modules/,
              use: {
                loader: 'babel-loader',
                options: {
                  presets: ['env'],
                  plugins: ['transform-runtime']
                }
              }
        },
        {
      test: /\.html$/,
      use: ['html-withimg-loader']
    },
        {
            test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
            loader: 'url-loader',
            query: {
                limit: 8000,
                name: 'img/[name].[hash:7].[ext]'
            }
        }, 
        {
            test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
            loader: 'url-loader',
            query: {
                limit: 8000,
                 name: 'font/[name].[hash:7].[ext]'
            }
        }
    ]
  },
    plugins:[
        new webpack.HotModuleReplacementPlugin(),
        new htmlWebpackPlugin({
          title:"首頁",
          template:'./src/index.html',
          filename:"index.html",
          chunks:["page/main/main"]
        }),
        new htmlWebpackPlugin({
          title:"購物車",
          template:'./src/index.html',
          filename:"car.html",
          chunks:["page/car/car"]
        }),
        new htmlWebpackPlugin({
          title:"商品",
          template:'./src/index.html',
          filename:"goods.html",
          chunks:["page/goods/goods"]
        }),

        new CleanWebpackPlugin(['dist']),
        extractSass,
        new webpack.ProvidePlugin({
             $:"jquery",
             jQuery:"jquery"
        }) 
        
    ]
}
上面這樣寫打包後文件都放在一個目錄下,目錄很亂,不方便管理,想讓每一個頁面的js,css文件放在對應目錄下,能夠按下面這麼寫
entry:{
    "page/main/main":'./src/js/index.js',
    "page/car/car":"./src/js/car.js",
    "page/goods/goods":"./src/js/goods.js"
  }
若是多個文件都引用了一些其餘庫,好比Jquery,vue,你可能想把全部的公共庫提取出來,利用common-chunk插件能夠解決。即便你作的是spa單頁面應用,你也能夠將公共庫從js文件中提取出來,每次修改時只修改業務邏輯而不從新打包庫,從而能夠緩存庫文件。
entry:{
        "main/main":'./src/js/index.js',
        "car/car":"./src/js/car.js",
        "goods/goods":"./src/js/goods.js"
        "vendor":["jquery","vue"]
  },

plugins:[     
        new htmlWebpackPlugin({
          ...同上
          chunks:["page/main/main","vendor","mainfest"]
        }),

        new htmlWebpackPlugin({
          ...
          chunks:["page/car/car","vendor","mainfest"]
        }),

        new htmlWebpackPlugin({
          ...
          chunks:["page/goods/goods","vendor","mainfest"]
        }),

         new webpack.optimize.CommonsChunkPlugin({
            name:["vendor","mainfest"]
        })
    ]
發現一個問題,在公司電腦dev-server-open自動打開的地址後面會帶undefined,去掉undefined打開網址才正常

代碼文件能夠上github查看

https://github.com/linrunzheng/webpackGuide

經常使用的配置就這樣了,其餘配置能夠去webpack官網看。若是以爲本文對你有所幫助,麻煩點個start或者贊

webpack3都出了,你還不會2嗎?

相關文章
相關標籤/搜索