webpack的入門篇能夠看個人這一片博文。
《如何使用webpack—webpack-howto》.css
最近一段時間在項目中使用了webpack和React來開發,總之來講也是遇到了許多坑,webpack畢竟仍是比較新的技術,並且也很難有一個很好的構建案例來適應全部的項目,總之,在看了許多項目demo和官方文檔以及官方推薦的tutorials以後,也算是本身總結出的一套最佳實踐吧。html
既然是須要用到的是實際項目的構建,那麼必然就要考慮開發環境和生產環境下的配置項了:node
// package.json { // ... "scripts": { "build": "webpack --progress --colors --watch", "watch": "webpack-dev-server --hot --progress --colors", "dist": "NODE_ENV=production webpack --progress --colors" }, // ... }
能夠在目錄下執行react
npm run build npm run watch npm run dist
解釋一下:webpack
build 是在咱們開發環境下執行的構建命令;git
watch 也是在開發環境下執行,可是加了webpack最強大的功能--搭建靜態服務器和熱插拔功能(這個在後面介紹;github
dist 是項目在要部署到生產環境時打包發佈。web
dist 裏面的NODE_ENV=production
是聲明瞭當前執行的環境是production-生產環境npm
後面跟着幾個命令:
--colors 輸出的結果帶彩色
--progress 輸出進度顯示
--watch 動態實時監測依賴文件變化而且更新
--hot 是熱插拔
--display-error-details 錯誤的時候顯示更多詳細錯誤信息
--display-modules 默認狀況下 node_modules 下的模塊會被隱藏,加上這個參數能夠顯示這些被隱藏的模塊
-w 動態實時監測依賴文件變化而且更新
-d 提供sorcemap
-p 對打包文件進行壓縮
如今前端模塊化的趨勢致使目錄結構也發生了很大的改變和爭議,這只是我本身用到的一種形式,能夠參考。
. ├── app #開發目錄 | ├──assets #存放靜態資源 | | ├──datas #存放數據 json 文件 | | ├──images #存放圖片資源文件 | | └──styles #存放全局sass變量文件和reset文件 | ├──lib | | ├──components #存放數據 模塊組件 文件 | | | └──Header | | | ├──Header.jsx | | | └──Header.scss | | | | | └──utils #存放utils工具函數文件 | | | └──views | ├──Index #入口文件 | | ├──Index.html #html文件 | | ├──Index.jsx | | └──Index.scss | └──Index2 ├── dist #發佈目錄 ├── node_modules #包文件夾 ├── .gitignore ├── .jshintrc ├── webpack.config.js #webpack配置文件 └── package.json
具體能夠到Github上看demo。
var webpack = require('webpack'); var path = require('path'); var fs = require('fs');
這個毋庸置疑吧。
定義函數判斷是不是在當前生產環境,這個很重要,一位開發環境和生產環境配置上有一些區別
var isProduction = function () { return process.env.NODE_ENV === 'production'; };
// 定義輸出文件夾 var outputDir = './dist'; // 定義開發文件夾 var entryPath = './app/views';
var plugins = [ new webpack.optimize.CommonsChunkPlugin({ name: 'commons', filename: 'js/commons.js', }), new webpack.ProvidePlugin({ React: 'react', ReactDOM: 'react-dom', reqwest: 'reqwest', }), ]; if( isProduction() ) { plugins.push( new webpack.optimize.UglifyJsPlugin({ test: /(\.jsx|\.js)$/, compress: { warnings: false }, }) ); }
CommonsChunkPlugin 插件能夠打包全部文件的共用部分生產一個commons.js文件。
ProvidePlugin 插件能夠定義一個共用的入口,好比下面加的 React ,他會在每一個文件自動require了react,因此你在文件中不須要 require('react')
,也可使用 React。
若是是在生產環境下,則加入插件 UglifyJsPlugin ,執行代碼壓縮,而且去除 warnings。
var entris = fs.readdirSync(entryPath).reduce(function (o, filename) { !/\./.test(filename) && (o[filename] = './' + path.join(entryPath, filename, filename + '.jsx')); return o; }, {} );
函數會自動遍歷開發的入口文件夾下面的文件,而後一一輩子產入口而且返回一個對象--入口。
那麼可使用html-webpack-plugin插件,它能夠自動爲入口生成一個html文件,配置以下:
var HtmlWebpackPlugin = require('html-webpack-plugin'); plugins.push(new HtmlWebpackPlugin({ title: 'index', filename: outputDir+'/index.html', #生成html的位置 inject: 'body', #插入script在body標籤裏 }));
entry 就能夠自定義一個入口就夠了
var config = { target: 'web', cache: true, entry: entris, output: { path: outputDir, filename: 'js/[name].bundle.js', publicPath: isProduction()? 'http://******' : 'http://localhost:3000', }, module: { loaders: [ { test: /(\.jsx|\.js)$/, loaders: ['babel?presets[]=es2015&presets[]=react'], exclude: /node_modules/ }, { test: /\.scss$/, loaders: ['style', 'css?root='+__dirname, 'resolve-url', 'sass'] }, { test: /\.json$/, loader: 'json', }, { test: /\.(jpe?g|png|gif|svg)$/, loader: 'url?limit=1024&name=img/[name].[ext]' }, { test: /\.(woff2?|otf|eot|svg|ttf)$/i, loader: 'url?name=fonts/[name].[ext]' }, { test: /\.html$/, loader: 'file?name=views/[name].[ext]' }, ] }, plugins: plugins, resolve: { extensions: ['', '.js', 'jsx'], }, devtool: isProduction()?null:'source-map', };
這裏來一一說明:
path和filename都不用多說了,path是生成文件的存放目錄,filename是文件名,固然能夠在前面加上目錄位置。
這裏提醒一下,filename 的相對路徑就是 path了,而且下面 靜態文件生成的filename也是相對於這裏的path的,好比 image 和 html。
publicPath 的話是打包的時候生成的文件連接,好比 圖片 資源,
若是是在生產環境固然是用服務器地址,若是是開發環境就是用本地靜態服務器的地址。
能夠不用夾 loader了 好比 原來 url-loader 如今 url
{ test: /(\.jsx|\.js)$/, loaders: ['babel?presets[]=es2015&presets[]=react'], exclude: /node_modules/ },
對於js文件和jsx文件用了babel來處理,這裏注意一下,最新版本的babel吧es2015和react的處理分開了,全部要這麼寫。
{ test: /\.scss$/, loaders: ['style', 'css?root='+__dirname, 'resolve-url', 'sass'] },
這裏用了sass、css、style的loader這不用多說了。
那麼root和resolve-url是怎麼回事呢,root是定義了scss文件裏面聲明的url地址是相對於根目錄的,而後resolve-url回去相對解析這個路徑,而不用require去獲取,好比
background: url('./assets/images/webpack.png');
這樣就能夠加載到./assets/images/webpack.png
這個文件,而不用使用相對路徑和require
{ test: /\.json$/, loader: 'json', },
對於json文件,能夠自動請求該模塊而且打包。
{ test: /\.(jpe?g|png|gif|svg)$/, loader: 'url?limit=1024&name=img/[name].[ext]' }, { test: /\.(woff2?|otf|eot|svg|ttf)$/i, loader: 'url?name=fonts/[name].[ext]' },
這裏使用了 url 這個loader,可是url依賴 file-loader,它是對file-loader的二次封裝。
在請求圖片的時候若是文件大小小於 1024k ,使用內聯 base64 URLs,不然會自動導入到name所聲明的目錄,這裏是相對以前聲明的 outputDir 路徑。
字體資源也是同樣。
{ test: /\.html$/, loader: 'file?name=views/[name].[ext]' },
在多頁面的項目中須要,能夠自動吧html文件導入到指定的生產文件夾下。
resolve: { extensions: ['', '.js', 'jsx'], },
是能夠忽略的文件後綴名,好比能夠直接require('Header');
而不用加.jsx。
devtool: isProduction()?null:'source-map',
規定了在開發環境下才使用 source-map。
目前爲止,對於多頁面項目仍是沒有找到一個很好的方案去構建自動化。
原文能夠看個人博客 webpack-best-practice-最佳實踐-部署生產;