react + webpack 項目搭建

經常使用配置說明

  • entryjavascript

    • 能夠接受字符串,數組,對象等多種格式
    • 項目打包入口文件,能夠是絕對路徑也能夠是相對路徑
    • webpack 打包默認入口文件是 ./src/index.js 約定,默認輸出是 項目根目錄下 /dist/main.js
  • output 打包後的內容輸出相關配置,path打包後文件路徑, 只能使用絕對路徑css

  • 經常使用loader相關理解html

    • 默認狀況下,webpack 值支持.js,.json文件,經過 loader,可讓他解析其餘類型的文件(.css, .less, .ts, .vue ....),充當翻譯官的角色。理論上只要有響應的 loader,就能夠處理任何文件。一個 loader 只幹一件事,webpack 的約定
    • 同一後綴文件使用多個 loader 時,loader 有執行順序,從右向左依次執行
    • css-loader只是把 css 代碼打包進 js 文件而已,並不作任何操做
    • style-loader 提取css-loader打包後的css代碼,並自動生成標籤,而後插入 html 中
    • less-loader 只是把 less 語法編譯爲 css 語法,而後 css-loader 把編譯好的 css 內容插入 js 文件中,最後 style-loader 把 css 添加到標籤並動態插入到 html 文件標籤中
    • postcss-loader使用順序,放在可以拿到 css 內容的地方就能夠,拿到 css 內容,經過一些 js 插件處理 css 達到加強 css 的效果
  • loader 和 plugin 區別:loader 的主要職責是讓 webpack 認識更多的文件類型,而 plugin 的職責是讓其能夠控制構建流程,從而執行一些特殊的任務。至關於 webpack 的功能補充。vue

hash,chunkhash,contenthash

若是不指定 hash 類型,webpack 默認是用 hash。java

文件使用 hash 名的目的是爲了利用瀏覽器的緩存,當咱們作下次功能迭代的時候,只修改某一個文件的時候,hash 發生變化, 可是其餘文件沒有變化,hash 不變則會走緩存,變化的就會從新請求,這樣能夠減小請求node

  1. hash 是隨整個工程內容的變化而變化
  2. chunkhash 隻影響一個 chunk 下的模塊,一個文件所依賴的代碼塊會打包進一個 chunk
  3. contenthash 只根據自身的內容變化 而變化, 可是若是 contenthash 發生變化,他所屬的 chunkhash 也會變化

項目目錄結構

.  
|-- src                             項目源代碼  
  |-- components                    項目通用組件
  |-- pages                         項目功能模塊
    |-- index.js                    項目入口文件
|-- static                          項目靜態資源,圖片,字體文件  
|-- webpack                         webpack 打包相關的配置  
  |-- config.js                     通用配置變量抽離
  |-- webpack.config.common.js      webpack 公共配置
  |-- webpack.config.dev.js         本地開發環境打包配置
  |-- webpack.config.production.js  正式環境打包配置
  |-- config.js
|-- index.html                      打包模板
|-- .babelrc                        babel 相關配置文件
|-- postcss.config.js               postcss 相關配置文件
|-- .npmrc                          npm 安裝源設置
|-- package.json         
複製代碼

完整的項目打包方案

webpack.config.common.js

const path = require('path');
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const webpack = require("webpack");

module.exports = {
  entry: {
    index: './src/pages/index.js',
  },
  resolve: {
    // 項目路徑別名
    alias: {
      Utils: path.resolve(__dirname, "../src/utils"),
      Components: path.resolve(__dirname, "../src/components"),
    },
  },
  performance: {
    // false | "error" | "warning" // 不顯示性能提示 | 以錯誤形式提示 | 以警告...
    hints: false,
    // 開發環境設置較大防止警告
    // 根據入口起點的最大致積,控制webpack什麼時候生成性能提示,整數類型,以字節爲單位
    maxEntrypointSize: 5000000,
    // 最大單個資源體積,默認250000 (bytes)
    maxAssetSize: 3000000,
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        use: 'babel-loader',
        include: path.resolve(__dirname, "../src"),
        exclude: /node_modules/,
      },
    ]
  },
  plugins: [
    new CleanWebpackPlugin(), // 每次打包前先清除以前的打包內容
    new HtmlWebpackPlugin({
      template: "./index.html", // 打包 html 模板
      filename: "index.html", // 打包後生成的文件名
    }),
    new webpack.DefinePlugin({ // 自定義項目環境變量,此處用於二級目錄部署
      "process.env": {
        SECONDARY_PATH: JSON.stringify(process.env.SECONDARY_PATH),
      },
    }),
  ]
}複製代碼

webpack.config.dev.js

const path = require("path");
const config = require("./config");
const webpack = require("webpack");
const { merge } = require("webpack-merge");

const common = require("./webpack.config.common.js");

module.exports = merge(common, {
  mode: "development",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "[name]-[hash:6].js",
    publicPath: config.publicPath,
    chunkFilename: "[name].[chunkhash:4].chunk.js",
  },
  devServer: {
    port: 8089,
    host: "0.0.0.0",
    hot: true, // css 修改熱更新,js 熱更新須要配合 hotOnly和webpack.HotModuleReplacementPlugin()
    compress: true,
    // 當使用 HTML5 History API 時, 全部的 404 請求都會響應 index.html 的內容。 將 devServer.historyApiFallback 設爲 true開啓:
    historyApiFallback: true, 
    hotOnly: true, // 即使HMR不⽣效,瀏覽器也不⾃動刷新,就開啓hotOnly
    /* proxy: {   // 每一個 key 都是須要轉發的前綴
      "/dataassets/api": {
        target: "後端接口服務地址",
      },
    }, */
    proxy: [
      // 多個前綴代理到同一個後端服務寫法
      {
        context: ["/dataassets/api", "/sso"],
        target: "後端接口服務地址",
      },
    ]
  },
  devtool: "inline-source-map", // 開發環境配置
  module: {
    rules: [
      {
        test: /\.(less|css)$/,
        use: [
          "style-loader",
          "css-loader",
          {
            loader: "less-loader",
            options: {
              // less@3
              javascriptEnabled: true,
              // 覆蓋antd樣式的全局變量
              modifyVars: config.modifyVars,
              globalVars: {
                imgUri: `~"${config.publicPath}"`,
              },
            },
          },
        ],
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        use: [
          "file-loader?hash=sha512&digest=hex&name=[hash].[ext]",
        ],
      },
      {
        test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        use: "url-loader?limit=10000&mimetype=application/font-woff",
      },
      {
        test: /\.(ttf|eot)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        use: "file-loader",
      },
    ],
  },
  plugins: [new webpack.HotModuleReplacementPlugin()],
});複製代碼

webpack.config.production.js

const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const { merge } = require("webpack-merge");
const config = require("./config");
const common = require("./webpack.config.common.js");

module.exports = merge(common, {
  mode: "production",
  output: {
    path: path.resolve(__dirname, "../dist"),
    publicPath: config.publicPath, // 項目打包後的 css,js 都會添加統一訪問路徑前綴
    filename: "js/[name].[hash:6].js",
    chunkFilename: "js/[name].[hash:6].chunk.js",
  },
  module: {
    rules: [
      {
        test: /\.(less|css)$/,
        use: [
          {
            // MiniCssExtractPlugin 既有插件的配置也有 loader 的配置,具體配置項參考 github 文檔
            // https://github.com/webpack-contrib/mini-css-extract-plugin
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: config.publicPath, // 配置打包後訪問 css 文件的路徑前綴。
            },
          },
          "css-loader",
          "postcss-loader",
          {
            loader: "less-loader",
            options: {
              // less@3
              javascriptEnabled: true,
              // 覆蓋antd樣式的全局變量
              modifyVars: config.modifyVars,
              globalVars: {
                imgUri: `~"${config.publicPath}"`, // 用於設置樣式文件裏引入的 image 圖片地址前綴
              },
            },
          },
        ],
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: "[name]-[contenthash:6].[ext]",
              limit: 2 * 1024, // 小於2k的圖片,直接使用Base64編碼進行處理
              publicPath: config.publicPath
            }
          }
        ],
      },
      {
        test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              publicPath: config.publicPath
            }
          }
        ]
      },
      {
        test: /\.(ttf|eot)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              publicPath: config.publicPath
            }
          }
        ]
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "css/[contenthash:6]-[name].css",
    }),
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, "../static"),
        to: path.resolve(__dirname, "../dist/static"),
      },
    ]),
  ],
});複製代碼
相關文章
相關標籤/搜索