搭建 webpack + React 開發環境

來源:互聯網
上載者:User

標籤:安裝   war   文章   支援   查看   hunk   scss   tor   comm   

說在開頭

上個月斷斷續續的在研究webpack的配置,但是很多網上的文章基本上都是只說了開發環境的配置,而忽略了生產環境的配置。大致研究了一下門路,然後就來寫一篇隨筆讓自己能在以後能有個地方可以做參考。

本文開始

我就假裝大家都是裝了node的情況下。

1、進入項目目錄,運行`npm init`按照步驟填寫最終產生`package.json`檔案,所有使用 npm 做依賴管理的項目,根目錄下都會有一個這個檔案,該檔案描述了項目的基本資料以及一些第三方依賴項(外掛程式)。詳細的使用說明可查閱[官網文檔],不過是英文的。 2、已知我們將使用 webpack 作為構建工具,那麼就需要安裝相應外掛程式,運行 `npm install webpack webpack-dev-server --save-dev` 來安裝兩個外掛程式。又已知我們將使用 React ,也需要安裝相應外掛程式,運行 `npm i react react-dom --save`來安裝兩個外掛程式。其中`i`是`install`的簡寫形式。安裝完成之後,查看`package.json`可看到多了`devDependencies`和`dependencies`兩項,根目錄也多了一個`node_modules`檔案夾。 3、`--save` 和 `--save-dev` 的區別`npm i`時使用`--save`和`--save-dev`,可分別將依賴(外掛程式)記錄到`package.json`中的`dependencies`和`devDependencies`下面。`dependencies`下記錄的是項目在運行時必須依賴的外掛程式,常見的例如`react` `jquery`等,即使項目打包好了、上線了,這些也是需要用的,否則程式無法正常執行。`devDependencies`下記錄的是項目在開發過程中使用的外掛程式,例如這裡我們開發過程中需要使用`webpack`打包,但是一旦項目打包發布、上線了之後,`webpack`就都沒有用了,可卸磨殺驢。延伸一下,我們的項目有`package.json`,其他我們用的項目如`webpack`也有`package.json`,見`./node_modules/webpack/package.json`,其中也有`devDependencies`和`dependencies`。當我們使用`npm i webpack`時,`./node_modules/webpack/package.json`中的`dependencies`會被 npm 安裝上,而`devDependencies`也沒必要安裝。 4、webpack.config.js為了提高學習效率,webpack 最最基礎的用法,就不再挨個示範了(推薦一個非常好的[入門文章],以及[更多資料])這裡我們把項目中的`webpack.config.js`這個設定檔詳細的講解一下,過程中也會照顧 0 基礎的同學。webpack.config.js 就是一個普通的 js 檔案,符合 commonJS 規範。最後輸出一個對象,即`module.exports = {...}`這個比較基礎,不過需要建立`./app/index.js`作為入口檔案,目前項目中只有這一個入口檔案。不過 webpack 支援多個入口檔案,可查閱文檔。輸出就是一個`bundle.js`,js 和 css 都在裡面,不過只有在開發環境下才用,發布代碼的時候,肯定不能只有這麼一個檔案,接下來會講到。  module針對不同類型的檔案,使用不同的`loader`,當然使用之前要安裝,例如`npm i style-loader css-loader --save-dev`。該項目代碼中,我們用到的檔案格式有:js/jsx 代碼、css/less 代碼、圖片、字型檔。less 是 css 的文法糖,可以更高效低冗餘的寫 css,不熟悉的朋友可去[官網]看看,非常簡單。在載入 css/less 時用到了`postcss`,主要使用`autoprefixer`功能,協助自動加 css3 的瀏覽器首碼,非常好用。編譯 es6 和 jsx 文法時,用到家喻戶曉的`babel`,另外還需增加一個`.babelrc`的設定檔。 plugins使用 html 模板(需要`npm i html-webpack-plugin --save-dev`),這樣可以將輸出的檔案名稱(如`./bundle.js`)自動注入到 html 中,不用我們自己手寫。手寫的話,一旦修改就需要改兩個地方。使用熱載入和自動開啟瀏覽器外掛程式 devServer對 webpack-dev-server 的配置 npm start在 package.json 中,輸入以下代碼,將這一串命令封裝為`npm start`,這樣就可以運行項目代碼了。 
"scripts": {"start": "NODE_ENV=dev webpack-dev-server --progress --colors"}
 代碼中`NODE_ENV=dev`代表當前是開發環境下,這裡的`"dev"`可被 js 代碼中的`process.env.NODE_ENV`得到並做一些其他處理。 5、定義環境全域變數以下定義,可使得代碼通過`__DEV__`得到當前是不是開發模式。
new webpack.DefinePlugin({__DEV__: JSON.stringify(JSON.parse((process.env.NODE_ENV == ‘dev‘) || ‘false‘))})

 


開啟`./app/util/localStore.js`可以看到`if (__DEV__) { console.error(‘localStorage.getItem報錯, ‘, ex.message) }`,即只有開發環境下才提示error,發布之後就不會提示了。(因為發布的命令中用到`NODE_ENV=production`) 6、生產環境的配置 webpack.production.config.js開發環境下,可以不用考慮系統的效能,更多考慮的是如何增加開發效率。而發布系統時,就需要考慮發布之後的系統的效能,包括載入速度、緩衝等。下面介紹發布用配置代碼和開發用的不一樣的地方。發布到 `./build` 檔案夾中 : `path: __dirname + "/build",` vendor將第三方依賴單獨打包。即將 node_modules 檔案夾中的代碼打包為 vendor.js 將我們自己寫的業務代碼打包為 app.js。這樣有助於緩衝,因為在項目維護過程中,第三方依賴不經常變化,而業務代碼會經常變化。 md5尾碼為每個打包出來的檔案都加md5尾碼,例如`"/js/[name].[chunkhash:8].js"`,可使檔案強緩衝。 分目錄打包出來的不同類型的檔案,放在不同目錄下,例片檔案將放在`img/`目錄下 Copyright自動為打包出來的代碼增加 copyright 內容 分模組`new webpack.optimize.OccurenceOrderPlugin(),` 壓縮代碼使用 Uglify 壓縮代碼,其中`warnings: false`是去掉代碼中的 warning 分離 css 和 js 檔案開發環境下,css 代碼是放在整個打包出來的那個 bundle.js 檔案中的,發布環境下當然不能混淆在一起,使用`new ExtractTextPlugin(‘/css/[name].[chunkhash:8].css‘),`將 css 代碼分離出來。 7、npm run build開啟`package.json`,查看以下代碼。`npm start`和`npm run build`分別是運行代碼和打包項目。另外,`"start"、"test"`可以不用`run`。
 
"scripts": {"start": "NODE_ENV=dev webpack-dev-server --progress --colors","build": "rm -rf ./build && NODE_ENV=production webpack --config ./webpack.production.config.js --progress --colors"},

 


這兩個命令主要有以下區別:
- 前者中預設使用 webpack.config.js 作為設定檔,而後者中強制使用 webpack.production.config.js 作為設定檔- 前者`NODE_ENV=dev`而後者`NODE_ENV=production`,標識不同的環境。而這個`"dev" "production"`可以在代碼中通過`process.env.NODE_ENV`擷取。  最小化壓縮 React以下配置可以告訴 React 當前是生產環境,請最小化壓縮 js ,即把開發環境中的一些提示、警告、判斷通通去掉,直流以下發布之後可用的代碼。
new webpack.DefinePlugin({‘process.env‘:{‘NODE_ENV‘: JSON.stringify(process.env.NODE_ENV)}}),

 接下來把開發代環境的配置和生產環境的配置貼上

webpack.config.js

var path = require(‘path‘)var webpack = require(‘webpack‘)var HtmlWebpackPlugin = require(‘html-webpack-plugin‘);var OpenBrowserPlugin = require(‘open-browser-webpack-plugin‘);module.exports = {    entry: path.resolve(__dirname, ‘app/index.js‘),    output: {        filename: "bundle.js"    },    resolve: {        extensions: [‘‘, ‘.js‘, ‘.jsx‘]    },    module: {        loaders: [            { test: /\.(js|jsx)$/, exclude: /node_modules/, loader: ‘babel‘ },            { test: /\.less$/, exclude: /node_modules/, loader: ‘style!css!postcss!less‘ },            { test: /\.css$/, exclude: /node_modules/, loader: ‘style!css!postcss‘ },            { test:/\.(png|gif|jpg|jpeg|bmp)$/i, loader:‘url-loader?limit=5000‘ },  // 限制大小5kb            { test:/\.(png|woff|woff2|svg|ttf|eot)($|\?)/i, loader:‘url-loader?limit=5000‘} // 限制大小小於5k        ]    },    postcss: [        require(‘autoprefixer‘) //調用autoprefixer外掛程式,例如 display: flex    ],    plugins: [        // html 模板外掛程式        new HtmlWebpackPlugin({            template: __dirname + ‘/app/index.html‘        }),        //  熱載入        new webpack.HotModuleReplacementPlugin(),        // 開啟瀏覽器        new OpenBrowserPlugin({            url: ‘http://localhost:8080‘        }),        //  可在業務js代碼中使用 __DEV__ 判斷是否是開發環境 (dev模式下可以提示錯誤、測試報告等, production模式不提示)        new webpack.DefinePlugin({            __DEV__: JSON.stringify(JSON.parse((process.env.NODE_ENV == ‘dev‘) || ‘false‘)),        })    ],    devServer: {        proxy: {          // 凡是 `/api` 開頭的 http 請求,都會被代理到 localhost:3000 上,由 koa 提供 mock 資料。          // koa 代碼在 ./mock 目錄中,啟動命令為 npm run mock          ‘/api‘: {            target: ‘http://localhost:3000‘,            secure: false          }        },        colors: true, // 終端舒服為彩色        historyApiFallback: true, //不跳轉,在開發單頁應用時非常有用,它依賴於HTML5 history API,如果設定為true,所有的跳轉將指向index.html        inline: true, // 即時重新整理        hot: true, // 使用熱載入外掛程式 HotModuleReplacementPlugin    }}

webpack.production.config.js

var pkg = require(‘./package.json‘)var path = require(‘path‘)var webpack = require(‘webpack‘);var HtmlWebpackPlugin = require(‘html-webpack-plugin‘);var ExtractTextPlugin = require(‘extract-text-webpack-plugin‘);module.exports = {  entry: {    app: path.resolve(__dirname, ‘app/index.js‘),    // 將 第三方依賴(node_modules中的) 單獨打包    vendor: Object.keys(pkg.dependencies)  },  output: {    path: __dirname + "/build",    filename: "/js/[name].[chunkhash:8].js"  },  resolve:{      extensions:[‘‘, ‘.js‘,‘.jsx‘]  },  module: {    loaders: [        { test: /\.(js|jsx)$/, exclude: /node_modules/, loader: ‘babel‘ },        { test: /\.less$/, exclude: /node_modules/, loader: ExtractTextPlugin.extract(‘style‘, ‘css!postcss!less‘) },        { test: /\.css$/, exclude: /node_modules/, loader: ExtractTextPlugin.extract(‘style‘, ‘css!postcss‘) },        { test:/\.(png|gif|jpg|jpeg|bmp)$/i, loader:‘url-loader?limit=5000&name=img/[name].[chunkhash:8].[ext]‘ },        { test:/\.(png|woff|woff2|svg|ttf|eot)($|\?)/i, loader:‘url-loader?limit=5000&name=fonts/[name].[chunkhash:8].[ext]‘}    ]  },  postcss: [    require(‘autoprefixer‘)  ],  plugins: [    // webpack 內建的 banner-plugin    new webpack.BannerPlugin("Copyright by [email protected]"),    // html 模板外掛程式    new HtmlWebpackPlugin({        template: __dirname + ‘/app/index.html‘    }),    // 定義為生產環境,編譯 React 時壓縮到最小    new webpack.DefinePlugin({      ‘process.env‘:{        ‘NODE_ENV‘: JSON.stringify(process.env.NODE_ENV)      }    }),    // 為組件分配ID,通過這個外掛程式webpack可以分析和優先考慮使用最多的模組,並為它們分配最小的ID    new webpack.optimize.OccurenceOrderPlugin(),    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‘))    })  ]}

 

搭建 webpack + React 開發環境

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.