手把手教你webpack4.x從零開始搭建vue項目

1.首先安裝各個模塊所須要的依賴

  • npm init -y  初始化package.json文件 。

     如下全部安裝命令的 ‘-D‘  表明安裝在該文件的devDependencies中
     npm的文檔說明:dependencies是運行時依賴,devDependencies是開發時的依賴
css

  • npm i webpack webpack-cli webpack-dev-server webpack-merge -D

      webpack能夠看作是模塊打包機。webpack-cli封裝了與CLI處理相關的全部代碼。它捕獲選項並將它們發送到webpack編譯器。webpack-dev-server是webpack官方提供的一個小型express服務器, 爲webpack打包生成的資源文件提供web服務。webpack-merge是和用來區分兩個不一樣的環境html

  • npm i cross-env -D

      能夠跨平臺設置環境變量vue

  • npm i @babel/core babel-loader @babel/preset-env -D

      @babel/core是轉譯器自己,提供了babel的轉譯API。babel-loader就是調用這些API來完成轉譯js過程的。Babel 7宣佈廢棄babel-preset-es201x而採用新的env插件node

  • npm i  @babel/polyfill @babel/runtime-corejs2 @babel/plugin-transform-runtime -D

      Babel默認只轉換新的JavaScript句法,而不轉換新的API。須要在入口加載@babel/polyfill插件來轉換,能夠解決某些方法在IE的兼容性問題(這種方式是經過向全局對象和內置對象的prototype上添加方法實現的,會形成全局變量污染),在babel7.x版本中使用 :@babel/runtime-corejs2,能夠結合@babel/plugin-transform-runtime, 可避免全局污染。webpack

      在轉換 ES2015 語法爲 ECMAScript 5 的語法時,babel 會須要一些輔助函數,例如 _extend。babel 默認會將這些輔助函數內聯到每個 js 文件裏,這樣文件多的時候,項目就會很大。因此 babel 提供了 transform-runtime 來將這些輔助函數「搬」到一個單獨的模塊 babel-runtime 中,這樣作能減少項目文件的大小。web

  • npm i @babel/plugin-proposal-decorators -D

      將類和對象裝飾器編譯爲ES5express

  • npm i @babel/plugin-syntax-dynamic-import -D (在babel7.x中彷佛並不須要再進行單獨安裝)

     容許解析import() 延遲加載,懶加載
npm

  • npm i @babel/plugin-proposal-optional-chaining -D

     能夠訪問深層嵌套的屬性,能夠不用邏輯與去判斷    // const baz = obj?.foo?.bar?.baz
json

注意: babel7.0後,已經再也不使用@babel/preset-stage-x的預設了, 所需的插件都須要單獨去安裝配置,根據公司的項目須要,能夠選擇性的去配置 :@babel/plugin-***    這裏不作過多贅述。api

  • npm i vue-loader vue-template-compiler -D

       解析vue文件須要安裝這兩個插件

  • npm i uglifyjs-webpack-plugin -D

       用來在生產環境壓縮js

  • npm i css-loader sass node-sass sass-loader postcss-loader autoprefixer mini-css-extract-plugin optimize-css-assets-webpack-plugin -D

       css-loader處理css,用來解析@import這種語法。sass-loader將sass語言轉換成css, postcss-loader 和 autoprefixer用來爲css的樣式自動添加瀏覽器前綴,mini-css-extract-plugin是提取css文件,再也不以style標籤存放,而是建立link標籤引入,因此再也不須要style-loader。optimize-css-assets-webpack-plugin用來壓縮css

  • npm i url-loader file-loader -D

       url-loader打包圖片資源,file-loader打包字體等資源

  • npm i html-webpack-plugin clean-webpack-plugin copy-webpack-plugin -D

       html-webpack-plugin用來打包時自動生成html文件,clean-webpack-plugin打包時會自動清除dist,copy-webpack-plugin用來拷貝靜態資源到打包目錄

  • npx eslint --init, npm i babel-eslint -D

npx eslint --init 一鍵配置eslint規範。此外須要安裝babel-eslint工具。建立.eslintignore文件可設置忽略檢測的文件。在webstorm工具中設置eslint,編譯器能夠實時檢測,顯示錯誤

安裝完上述依賴以後,須要根據本身的安裝去配置.babelrc(babel的配置文件)和postcss.config.js。這裏直接附上我本身的配置僅供參考。以下:

  • .babelrc

{
  "presets": [
    "@babel/preset-env"
  ],
  "plugins": [
    ["@babel/plugin-transform-runtime", {
      "corejs": 2
    }],
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ],
    "@babel/plugin-proposal-optional-chaining"
  ]
}
複製代碼

  • postcss.config.js

module.exports = {  
  plugins: [
    require('autoprefixer')  
  ]
}複製代碼

2. webpack公共文件配置 :webpack.base.config.js

let path = require('path')
let MiniCssExtractPlugin = require('mini-css-extract-plugin')   // 提取css公共文件
let { VueLoaderPlugin } = require('vue-loader')     //vue-loader  15.x版本之後須要引入
let HtmlWebpackPlugin = require('html-webpack-plugin')    //自動生成html
let CopyWebpackPlugin = require('copy-webpack-plugin')  //拷貝靜態資源
let { CleanWebpackPlugin } = require('clean-webpack-plugin')  //打包前清除dist
let webpack = require('webpack')

module.exports = {
  entry: [ path.resolve(__dirname, '../src/main.js') ],
  output: {
    filename: 'js/[name].[hash:8].js',   //打包後的js文件放在js目錄下,添加hash值防止緩存
    chunkFilename: 'js/[name].[hash:8].js', // 配合按需加載路由來使用,用來修改打包後的各個JS模塊文件名字,具體請看下方打包後的截圖
    path: path.resolve(__dirname, '../dist'), //輸出的目錄
    publicPath: '/'     //靜態資源cdn的地址
  },
  stats: {     // 本地起服務或者打包時候,清除過多的日誌信息,精簡控制檯信息。
    modules: false,
    children: false,
    chunks: false,
    chunkModules: false,
    assets: false,  //不顯示資源打包信息
  },
  module: {   //轉換規則
    rules: [
      {
        test: /\.vue$/,
        exclude: /node_modules/,
        use: ['vue-loader']
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: ['babel-loader']
      },
      {
        test: /\.(css|scss|sass)$/,   
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'sass-loader'
        ]
      },
      {
        test: /\.(png|jpe?g|svg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 20 * 1024   // 不設置這個的話,打包後的圖片默認是超過8k時,會以base64編碼
              name: 'images/[name].[hash:8].[ext]'
            }
          }
        ]
      },
      {
        test:/\.(woff|woff2|eot|ttf|otf)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: 'fonts/[name].[hash:8].[ext]'
            }
          }
        ]
      },
    ]
  },
  resolve: {
    extensions: ['.vue', '.js', '.scss',  '.json'],// 可以使用戶在引入模塊時不帶擴展名字, 自動解析
    alias: {    //別名,方便快速查找模塊
      '@': path.resolve(__dirname, '../src')
    }
  },
  plugins: [
    new VueLoaderPlugin(),
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: path.resolve(__dirname, '../index.html'),
      title: '這是自定義的名字,請隨意',
      favicon: path.resolve(__dirname, '../src/images/logon.png'),  //瀏覽器標題的圖標
      hash: true,
      minify: {
        removeAttributeQuotes: true,    //刪除屬性的引號
        collapseWhitespace: true    //刪除空白符與摺疊行
      }
    }),
    new CleanWebpackPlugin(),
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../src/assets'),
        to: path.resolve(__dirname, '../dist/copyAssets')
      }
    ]),
    new MiniCssExtractPlugin({
      filename: 'css/[name].[hash:8].css'
    }),
    new webpack.ProgressPlugin()      //顯示打包進度的插件
  ]
}
複製代碼

3.webpack開發環境配置 :webpack.dev.config.js

let webpack = require('webpack') 
let path = require('path') 
let merge = require('webpack-merge')     
let base = require('./webpack.base.config')

module.exports = merge(base, {
  mode: 'development',     // 定義環境變量
  devtool: 'cheap-module-eval-source-map',
  devServer: {
    port: 8000,     //設置端口
    progress: true,// 控制檯顯示百分比,HDM進度
    hot: true,     // 啓用熱更新,控制檯所有刷新
    open: true,    // 自動打開瀏覽器
    historyApiFallback: true,
    contentBase: path.resolve(__dirname, '../dist'),
    proxy: {
      '/api': {        //url中匹配到'/api', 就會把'/api'以前的東西所有替換成target
        target: '',      // 目標服務器host
        changeOrigin: true,   //  表示要改變原始host
        secure: false,   // 默認請求的服務是https的, 而且證書是未認證的,因此須要關閉安全檢測。
        clentLogLevel: 'none',  //當使用內聯模式(inline mode)時,會在開發工具(DevTools)的控制檯(console)顯示消息,例如:在從新加載以前,在一個錯誤以前,或者 模塊熱替換(Hot Module Replacement) 啓用時。默認值是 info。
        pathRewrite: {
          '^/api': ''   // 重寫請求,源訪問地址中包含'/api'的將會替換爲空
        }
      }
    }
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),   //熱更新插件
    new webpack.NamedChunksPlugin()    // 使用此插件熱更新時控制檯會顯示模塊的相對路徑
  ]
})複製代碼

4.webpack生產環境配置 :webpack.prod.config.js

let merge = require('webpack-merge')
let base = require('./webpack.base.config')
let UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin')
let OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')

module.exports = merge(base, {
  mode: 'production',
  devtool: 'cheap-module-source-map',
  optimization: {
    minimizer: [
      new UglifyjsWebpackPlugin({   // 生產環境壓縮JS
        cache: true,    //是否否啓用緩存
        parallel: true,   //多通道並行處理
        sourceMap: false, //生產環境關閉源碼映射
        uglifyOptions: {
          warnings: false,    //清除警告
          compress:{
            drop_debugger: true,	// 清除degugger
            drop_console: true   //清除全部的console信息
          }
        }
      }),
      new OptimizeCssAssetsPlugin()   // 生產環境壓縮css
    ],
    splitChunks: {   //用於拆分代碼,找到 chunk 中共同依賴的模塊進行「提取」和「分離」到單獨的文件中,減小打包後體積,能夠避免內存溢出的問題。
      chunks: 'all'
    }
  },
   performance: {                       //  webpack 的性能提示
     hints: 'warning',                 // 顯示警告信息
     maxEntrypointSize: 5 * 1024 * 1024,    // 設置入口文件的最大致積爲5M  (以字節爲單位)
     maxAssetSize: 20* 1024 * 1024,        // 設置輸出文件的最大致積爲20M  (以字節爲單位)
     assetFilter (assetFilename) {        // 提供資源文件名的斷言函數
      return assetFilename.endsWith('.js') || assetFilename.endsWith('.css')
     }
    }
})
複製代碼

4.最後一步

在package.json文件的scripts中添加以下,而後執行npm run build便可打包

"serve": "cross-env NODE_ENV=development webpack-dev-server --config ./build/webpack.dev.config.js",
"build": "cross-env NODE_ENV=production webpack --config ./build/webpack.prod.config.js"
複製代碼

5.總結

       以上配置是採用webpack4.x+babel7.x版本,自行配置時請注意版本兼容問題。若是您想要升級項目到babel7.0, 文檔中也提供了一個升級工具:執行 npx babel-upgrade--write--install一鍵安裝babel7.0所須要的全部配置,而且會自動將配置寫入package.json和.babelrc文件中。詳情請參考文檔說明。如下是打包後的截圖:


copyAssets是拷貝的靜態資源。爲何打包後的js會有0**,2** 這麼幾個文件呢?這是由於我vue的路由使用了按需加載,每一個頁面都生成本身單獨的js。等須要的時候,纔會去加載這些js的。可是這個0, 1, 2,...等等的文件名字默認是以id命名的,這看起來不友好,並且不太方便排錯,因此須要在引入路由時候,須要使用特殊的註釋語法來提供webpackChunkName,配合output裏面設置的chunkFilename: 'js/[name].[hash:8].js' 來修改文件名,代碼以下:

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '',
      redirect: '/Home'
    },
    {
      path: '/Home',
      name: 'Home',
      component: () => import(/* webpackChunkName: 'Home' */ '@/view/Home')
    },
    {
      path: '/Hello',
      name: 'Hello',
      component: () => import(/* webpackChunkName: 'Hello' */ '@/view/Hello')
    }
  ]
})複製代碼

最終打包後的結果以下,看看,這就舒服多了~

相關文章
相關標籤/搜索