Webpack3搭建React項目詳細教程(兼容Webpack4)

源碼地址:https://github.com/remmlqw/we...
注意:本文是從 Webpack3 搭建 兼容 Webpack4css

新建項目

一、新建一個文件夾html

npm init

一直回車,最後yes,生成package.json前端

二、文件夾中新建如下文件node

src                            --源碼
index.html                     --入口首頁
webpack.config.js              --webpack開發環境配置
webpack.production.config.js   --webpack生產環境配置

下載依賴包

先下載幾個基本的包,後續還會用到其餘包。react

打包工具
webpack webpack

輔助開發的服務器(該服務器能熱加載代碼,自動刷新頁面,代理服務器解決前端開發時跨域問題)
webpack-dev-server git

在webpack 3中,webpack自己和它的CLI之前都是在同一個包中,但在第4版中,他們已經將二者分開來更好地管理它們。因此還要安裝:
webpack-cli
注:這裏除了本地安裝外,還需全局安裝 npm i webpack-cli -ges6

react用到es6語法,因此要安裝es6轉碼器babel相關的包
babel-core
babel-loader
babel-preset-env
babel-preset-reactgithub

webpack須要處理樣式文件打包的處理器
css-loader
style-loader
less-loaderweb

webpack須要處理圖片文件打包的處理器
file-loader
url-loader

以上包的下載使用 npm i XXX --save-dev
--save-dev 是寫入開發環境的依賴


react項目的兩個基礎包
react
react-dom

這兩個包下載使用 npm i XXX --save
--save 是寫入生產環境的依賴

package.json中的scripts

在package.json中的scripts加上兩個key

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "cross-env NODE_ENV=dev webpack-dev-server --inline --progress --colors --mode development",
    "build": "cross-env NODE_ENV=production webpack --config ./webpack.production.config.js --progress --colors --mode production"
  },

這裏須要安裝的一個包 npm i cross-env --save-dev
有何用?
windows不支持 NODE_ENV=development 的設置方式,這個包可以提供一個設置環境變量的scripts,讓你可以以unix方式設置環境變量,而後在windows上也能兼容運行。cross-env 讓這一切變得簡單,不一樣平臺使用惟一指令,無需擔憂跨平臺問題。

--progress 顯示打包過程當中的進度
--colors 打包信息帶有顏色顯示
--inline 自動刷新的配置
--mode development/production webpack 4引入了生產和開發模式,自動根據開發和生產兩種模式進行優化

webpack --config ./webpack.production.config.js
這個命令是制定webpack的配置文件,由於默認的是webpack.config.js,而這裏是打包命令,應該使用webpack.production.config.js

開發環境配置 --webpack.config.js

先上完整代碼

const path=require('path');
const webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin');
var OpenBrowserPlugin = require('open-browser-webpack-plugin');

// 配置文件的內容須要經過module.exports暴露
module.exports = {
  // 配置須要打包的入口文件,值能夠是字符串、數組、對象。
  // 1. 字符串: entry: './entry'
  // 2. 字符串: entry:[ './entry1','entry2'] (多入口)
  // 3. 對象:   entry: {alert/index': path.resolve(pagesDir, `./alert/index/page`)}
  // 多入口書寫的形式應爲object,由於object,的key在webpack裏至關於此入口的name,
  entry : './src/js/index.js',
  output : {
    // 輸出文件配置,output 輸出有本身的一套規則,經常使用的參數基本就是這三個
    // path: 表示生成文件的根目錄 須要一個**絕對路徑** path僅僅告訴Webpack結果存儲在哪裏
    path : path.resolve(__dirname,'dist'),
    // filename 屬性表示的是如何命名出來的入口文件
    filename : './js/bundle.js'
  },
  resolve: {
    //自動擴展文件後綴名,意味着咱們require模塊能夠省略不寫後綴名
    extensions: ['*', '.js', '.json', '.less','.jsx'],
    //模塊別名定義,方便後續直接引用別名,無須多寫長長的地址
    alias: {
      '@components': path.resolve(__dirname,'src/js/components')
    }
  },
  module : {
    // 這裏就是Loader,經過Loader,webpack可以針對每一種特定的資源作出相應的處理
    // 1.test參數用來指示當前配置項針對哪些資源,該值應是一個條件值(condition)。
    // 2.exclude參數用來剔除掉須要忽略的資源,該值應是一個條件值(condition)。
    // 3.include參數用來表示本loader配置僅針對哪些目錄/文件,該值應是一個條件值(condition)。
    // 而include參數則用來指示目錄;注意同時使用這二者的時候,其實是and的關係。
    // 4.use參數,用來指示用哪一個或哪些loader來處理目標資源。
    rules : [
      {
        test: /\.(js|jsx)$/,
        use : {
          loader : "babel-loader",
          options : {
            presets : ['env','react']
          }
        },
        exclude : /node_modules/
      },
      {
        test: /\.less$/,
        exclude: /node_modules/,
        use : [{loader : "style-loader"},{loader : "css-loader"},{loader : "less-loader"}]
      },
      {
        test : /\.css$/,
        use : [{loader : "style-loader"},{loader : "css-loader"}]
      },
      {
        test: /\.(png|gif|jpg|jpeg|bmp)$/i,
        use : {
          loader : 'url-loader',
          options : {
            limit : '8192'
          }
        }
      },
      {
        test: /\.(woff|woff2|svg|ttf|eot)($|\?)/i,
        use: {
          loader: 'url-loader',
          options: {
            limit: '8192'
          }
        }
      }
    ]
  },
  plugins: [
    // html 模板插件
    new HtmlWebpackPlugin({
        template: __dirname + '/index.html'
    }),

    // 熱加載插件
    new webpack.HotModuleReplacementPlugin(),

    // 打開瀏覽器
    new OpenBrowserPlugin({
      url: 'http://localhost:8080'
    }),

    // 可在業務 js 代碼中使用 __DEV__ 判斷是不是dev模式(dev模式下能夠提示錯誤、測試報告等, production模式不提示)
    new webpack.DefinePlugin({
      __DEV__: JSON.stringify(JSON.parse((process.env.NODE_ENV == 'dev') || 'false'))
    }),

  ],
  //咱們在這裏對webpack-dev-server進行配置
  devServer: {
    contentBase:"./",// 本地服務器在哪一個目錄搭建頁面,通常咱們在當前目錄便可;
    historyApiFallback:true,//當咱們搭建spa應用時很是有用,它使用的是HTML5 History Api,任意的跳轉或404響應能夠指向 index.html 頁面;
    inline:true,//用來支持dev-server自動刷新的配置,webpack有兩種模式支持自動刷新,一種是iframe模式,一種是inline模式;使用iframe模式是不須要在devServer進行配置的,只需使用特定的URL格式訪問便可;不過咱們通常仍是經常使用inline模式,在devServer中對inline設置爲true後,當咱們啓動webpack-dev-server時仍要須要配置inline才能生效
    hot:true,// 啓動webpack熱模塊替換特性,這裏是個坑
    port:8080,//配置服務端口號
    host:'localhost',//服務器的IP地址,可使用IP也可使用localhost
    compress:true,//服務端壓縮是否開啓
  }
}

相關參數配置的說明已經寫在代碼的註釋裏。

這裏對於上面使用的插件我在作一下說明:

html-webpack-plugin :html-webpack-plugin能夠根據你設置的模板,在每次運行後生成對應的模板文件,同時所依賴的CSS/JS也都會被引入,若是CSS/JS中含有hash值,則html-webpack-plugin生成的模板文件也會引入正確版本的CSS/JS文件。詳細介紹https://www.npmjs.com/package...

webpack.HotModuleReplacementPlugin:模塊熱替換(HMR - Hot Module Replacement)功能會在應用程序運行過程當中替換、添加或刪除模塊,而無需從新加載整個頁面。主要是經過如下幾種方式,來顯著加快開發速度:
保留在徹底從新加載頁面時丟失的應用程序狀態。
只更新變動內容,以節省寶貴的開發時間。
調整樣式更加快速 ,幾乎至關於在瀏覽器調試器中更改樣式。
詳細介紹https://doc.webpack-china.org...

open-browser-webpack-plugin : 則在webpack 啓動成功後會打開瀏覽器。詳細介紹https://www.npmjs.com/package...

webpack.DefinePlugin : 可在業務 js 代碼中使用 DEV 判斷是不是dev模式。詳細介紹https://doc.webpack-china.org...

好比

if(__DEV__) {
    console.log("如今是開發環境");
}
else {
    console.log("如今是生產環境");
}

這裏須要額外安裝的包:
html-webpack-plugin
open-browser-webpack-plugin

生產環境配置 --webpack.production.config.js

一樣的,先上完整代碼:

var path = require('path')
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var autoprefixer = require('autoprefixer');
var OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');

module.exports = {
  entry: {
    app: path.resolve(__dirname, './src/js/index.js'),
    // 將 第三方依賴 單獨打包
    vendor: ['react', 'react-dom']
  },
  output: {
    path: __dirname + "/dist",
    // filename 屬性表示的是如何命名出來的入口文件,規則是一下三種:
    // [name] 指代入口文件的name,也就是上面提到的entry參數的key,所以,咱們能夠在name裏利用/,便可達到控制文件目錄結構的效果。
    // [hash],指代本次編譯的一個hash版本,值得注意的是,只要是在同一次編譯過程當中生成的文件,這個[hash].js
    //的值就是同樣的;在緩存的層面來講,至關於一次全量的替換。
    filename: "js/[name].[chunkhash:8].js",
    // publicPath 參數表示的是一個URL 路徑(指向生成文件的跟目錄),用於生成css/js/圖片/字體文件
    // 等資源的路徑以確保網頁能正確地加載到這些資源.
    // 「publicPath」項則被許多Webpack的插件用於在生產模式下更新內嵌到css、html文件裏的url值.
    // 例如,在localhost(即本地開發模式)裏的css文件中邊你可能用「./test.png」這樣的url來加載圖片,
    // 可是在生產模式下「test.png」文件可能會定位到CDN上而且你的Node.js服務器多是運行在HeroKu上邊的。
    // 這就意味着在生產環境你必須手動更新全部文件裏的url爲CDN的路徑。
    //開發環境:Server和圖片都是在localhost(域名)下
    //.image {
    // background-image: url('./test.png');
    //}
    // 生產環境:Server部署下HeroKu可是圖片在CDN上
    //.image {
    //  background-image: url('https://someCDN/test.png');
    //}
    publicPath: './'
  },

  resolve: {
    //自動擴展文件後綴名,意味着咱們require模塊能夠省略不寫後綴名
    extensions: ['*', '.js', '.json', '.less','.jsx'],
    //模塊別名定義,方便後續直接引用別名,無須多寫長長的地址
    alias: {
      '@components': path.resolve(__dirname,'src/js/components')
    }
  },

  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ['env', 'react']
          }
        }
      }, {
        test: /\.less$/,
        exclude: /node_modules/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader', 'postcss-loader', 'less-loader']
        })
      }, {
        test: /\.css$/,
        // exclude: /node_modules/, 刪掉次行  否則打包會報錯  由於antd.css 在node_modules中
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader', 'postcss-loader']
        })
      }, {
        test: /\.(png|gif|jpg|jpeg|bmp)$/i,
        use: {
          loader: 'url-loader',
          options: {
            limit: '8192',
            outputPath: 'images/',
            publicPath : '/images'
          }
        }
      }, {
        test: /\.(woff|woff2|svg|ttf|eot)($|\?)/i,
        use: {
          loader: 'url-loader',
          options: {
            limit: '8192',
            outputPath: 'font/'
          }
        }
      }
    ]
  },
  plugins: [
    // webpack 內置的 banner-plugin
    new webpack.BannerPlugin("Copyright by 765745342@qq.com"),

    // html 模板插件
    new HtmlWebpackPlugin({
      template: __dirname + '/index.html'
    }),

    // 定義爲生產環境,編譯 React 時壓縮到最小
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify(process.env.NODE_ENV)
      }
    }),

    // 爲組件分配ID,經過這個插件webpack能夠分析和優先考慮使用最多的模塊,併爲它們分配最小的ID
    new webpack.optimize.OccurrenceOrderPlugin(),

    new webpack.optimize.UglifyJsPlugin({
      compress: {
        //supresses warnings, usually from module minification
        warnings: false
      }
    }),

    // 分離CSS和JS文件
    new ExtractTextPlugin('css/[name].[chunkhash:8].css'),

    // 提供公共代碼
    new webpack.optimize.CommonsChunkPlugin({name: 'vendor', filename: 'js/[name].[chunkhash:8].js'}),

    // 可在業務 js 代碼中使用 __DEV__ 判斷是不是dev模式(dev模式下能夠提示錯誤、測試報告等, production模式不提示)
    new webpack.DefinePlugin({
      __DEV__: JSON.stringify(JSON.parse((process.env.NODE_ENV == 'dev') || 'false'))
    }),
    new OptimizeCssAssetsPlugin({
      assetNameRegExp: /\.css$/g,
      cssProcessor: require('cssnano'),
      cssProcessorOptions: { discardComments: {removeAll: true } },
      canPrint: true
    })
  ]
}

有些地方和 webpack.config.js 的配置是同樣的我就不作說明了。

extract-text-webpack-plugin : 開發環境下,css 代碼是放在整個打包出來的那個 bundle.js 文件中的,發佈環境下固然不能混淆在一塊兒。該插件的主要是爲了抽離css樣式,防止將樣式打包在js中引發頁面樣式加載錯亂的現象。詳細介紹https://www.npmjs.com/package...

webpack.optimize.CommonsChunkPlugin : 將第三方依賴單獨打包。即將 node_modules 文件夾中的代碼打包爲 vendor.js 將咱們本身寫的業務代碼打包爲 app.js。這樣有助於緩存,由於在項目維護過程當中,第三方依賴不常常變化,而業務代碼會常常變化。詳細介紹https://doc.webpack-china.org...

webpack.optimize.UglifyJsPlugin : 壓縮你的JS代碼。詳細介紹https://doc.webpack-china.org...

optimize-css-assets-webpack-plugin : CSS代碼壓縮。詳細介紹https://www.npmjs.com/package...

autoprefixer : Autoprefixer是一個後處理程序,你能夠同Sass,Stylus或LESS等預處理器共通使用。它適用於普通的CSS,而你無需關心要爲哪些瀏覽器加前綴,只需全新關注於實現,並使用W3C最新的規範。詳細介紹https://www.npmjs.com/package...
這是一個自動給你加上css瀏覽器前綴,好比
你只需寫:

a {
    display: flex;
}

這個插件自動給你添加廠商前綴:

a {
    display: -webkit-box;
    display: -webkit-flex;
    display: -ms-flexbox;
    display: flex;
}

這個插件請注意,你須要下載 postcss-loader
而且新建文件postcss.config.js
文件內容:

module.exports = {
  plugins: {
    'autoprefixer': {browsers: 'last 5 version'}
  }
}

這裏須要額外安裝的包:
postcss-loader
extract-text-webpack-plugin
optimize-css-assets-webpack-plugin

啓動項目

npm start

打包項目

npm run build

相關文章
相關標籤/搜索