本文來自網易雲社區css
做者:汪洋html
最近開發一個全新AB測試平臺,思考了下正好可使用react技術開發。前端
首先遇到一個概念,redux。這貨還真很差理解,大致的理解:Store包含全部數據,視圖觸發一個Action,Store收到Action後,返回一個新的 State,這樣視圖就發生變化,State計算過程叫作 Reducer,Reducer其實就是一個處理數據的函數,接受 Action和 當前State做爲參數,返回一個新的 State。
明白這個後,就能夠開始實踐了。node
對於我這方面沒搞過的菜鳥,還真是不容易。接下來講下做爲新手如何實踐的。react
第一步:依賴包webpack
"devDependencies": { "babel-core": "^6.26.0", "babel-eslint": "^8.2.2", "babel-loader": "^7.1.2", "babel-plugin-import": "^1.6.6", "babel-preset-es2015": "^6.22.0", "babel-preset-react": "^6.24.1", "babel-preset-stage-0": "^6.24.1", "css-loader": "^0.28.7", "eslint": "^4.18.2", "eslint-config-airbnb": "^16.1.0", "eslint-loader": "^2.0.0", "eslint-plugin-import": "^2.9.0", "eslint-plugin-jsx-a11y": "^6.0.3", "eslint-plugin-react": "^7.7.0", "extract-text-webpack-plugin": "^3.0.2", "html-webpack-plugin": "^3.0.4", "less": "^2.7.3", "less-loader": "^4.0.6", "style-loader": "^0.19.1", "url-loader": "^1.0.1", "webpack": "^3.1.0"},"dependencies": { "normalize.css": "^8.0.0", "react": "^16.2.0", "react-dom": "^16.2.0", "react-redux": "^5.0.7", "react-router-dom": "^4.2.2", "redux": "^3.7.2"}
dependencies 中引入的依賴包,是react的標配了,不用解釋。
devDependencies 中引入了 webpack,babel,babel插件,eslint語法檢測,eslint配置包airbnb,html模板資源替換插件 html-webpack-plugin,css提取插件 extract-text-webpack-plugin,less編譯相關插件,圖片等靜態資源路徑處理插件 url-loader。
這裏做爲新手,通常都是參考網上的配置,好比我就是github上找了個項目,摸索一下。推薦一本教程書《React全棧》,做者寫的很詳細,對入門絕對有幫助。
至此,基本依賴包已加載完。git
第二步:webpack配置 這裏不得不說,新手真不容易。 首先介紹下項目結構:
views/entry.html(靜態模板),
src/entry.jsx(入口文件),
src/actions(redux概念中Actions所在的文件夾) ,
src/reducers(redux概念中Reducers所在的文件夾) ,
src/store(redux概念中Store所在的文件夾) ,
src/pages(存放頁面的文件夾,jsx),
src/compinents(存放業務組件的文件夾,jsx),
src/style(公共樣式文件夾,less),
src/utils(幫助類文件夾),
src/constants(常量所在文件夾,保存各自的actions的type),
src/plugins(第三方插件文件夾),
build/(編譯後文件),
webpack/(webpack編譯配置所在文件夾),
.eslintrc(eslint配置文件),
.gitignore(git配置文件),
package.jsongithub
接下來就是webpack的配置了,先上代碼web
const path = require('path');const webpack = require('webpack');// html中替換編譯後的jsconst HtmlwebpackPlugin = require('html-webpack-plugin');// css提取const ExtractTextPlugin = require('extract-text-webpack-plugin');const ROOT_PATH = path.resolve(__dirname);const APP_PATH = path.resolve(ROOT_PATH, '../src');const BUILD_PATH = path.resolve(ROOT_PATH, '../build');module.exports = { entry: { entry: path.resolve(APP_PATH, './entry.jsx'), vendor: ['react', 'react-dom', 'pace'] }, output: { filename: '[name].js', path: BUILD_PATH, chunkFilename: '[name].js', publicPath: '../' }, devtool: 'eval-source-map', module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: [ { loader: 'babel-loader', query: { presets: ['es2015', 'react', 'stage-0'], plugins: ['syntax-dynamic-import', ['import', { libraryName: 'antd', style: 'css' }]] } } ] }, { test: /\.(css|less)$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: [ 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]', 'less-loader' ] }), exclude: /node_modules/ }, { test: /\.(css)$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: [ 'css-loader' ] }), include: /node_modules/ }, { test: /\.(jpg|jpeg|png|svg|gif|bmp)/i, use: [ 'url-loader?limit=5000&name=img/[name].[sha512:hash:base64:8].[ext]' ] }, { test: /\.(woff|woff2|ttf|eot)($|\?)/i, use: [ 'url-loader?limit=5000&name=fonts/[name].[sha512:hash:base64:8].[ext]' ] } ] }, resolve: { extensions: ['.js', '.jsx', '.less', '.css', '.png', '.jpg', '.svg', '.gif', '.eot'], alias: { pace: path.resolve(ROOT_PATH, '../src/plugins/pace/index.js'), ImagesPath: path.resolve(ROOT_PATH, '../src/') } }, devServer: { historyApiFallback: true, hot: true, inline: true, progress: true }, plugins: [ new webpack.optimize.CommonsChunkPlugin({ name: ['commons', 'vendor'], minChunks: 2 }), new ExtractTextPlugin('commons.css', { allChunks: true }), new HtmlwebpackPlugin({ template: path.resolve(ROOT_PATH, '../views/entry.html'), filename: path.resolve(ROOT_PATH, '../build/entry.html'), chunks: ['entry', 'vendor'], hash: false }), // 加署名 new webpack.BannerPlugin('Copyright by xxx') ] };
第一次接觸配置,真的找不到北,太多插件,太多功能。做爲新手,那須要怎麼個思路,我總結:按項目需求來配置。不要認爲其餘人配置的就適合本身項目,要否則給本身帶來各類麻煩。 摸索這個過程還挺長的:
A. 首先需求仍是明確的:less編譯、jsx編譯、公共文件單獨打包、html靜態模板中插入編譯後的文件路徑、css提取。 上面這些對應配置:編程
const path = require('path');const webpack = require('webpack');// html中替換編譯後的jsconst HtmlwebpackPlugin = require('html-webpack-plugin');// css提取const ExtractTextPlugin = require('extract-text-webpack-plugin');const ROOT_PATH = path.resolve(__dirname);const APP_PATH = path.resolve(ROOT_PATH, '../src');const BUILD_PATH = path.resolve(ROOT_PATH, '../build');module.exports = { entry: { entry: path.resolve(APP_PATH, './entry.jsx'), vendor: ['react', 'react-dom', 'pace'] }, output: { filename: '[name].js', path: BUILD_PATH, chunkFilename: '[name].js', publicPath: '../' }, devtool: 'eval-source-map', module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: [ { loader: 'babel-loader', query: { presets: ['es2015', 'react', 'stage-0'] } } ] }, { test: /\.(css|less)$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: [ 'css-loader', 'less-loader' ] }), exclude: /node_modules/ }, { test: /\.(jpg|jpeg|png|svg|gif|bmp)/i, use: [ 'url-loader?limit=5000&name=img/[name].[sha512:hash:base64:8].[ext]' ] }, { test: /\.(woff|woff2|ttf|eot)($|\?)/i, use: [ 'url-loader?limit=5000&name=fonts/[name].[sha512:hash:base64:8].[ext]' ] } ] }, plugins: [ new webpack.optimize.CommonsChunkPlugin({ name: ['commons', 'vendor'], minChunks: 2 }), new ExtractTextPlugin('commons.css', { allChunks: true }), new HtmlwebpackPlugin({ template: path.resolve(ROOT_PATH, '../views/entry.html'), filename: path.resolve(ROOT_PATH, '../build/entry.html'), chunks: ['entry', 'vendor'], hash: false }) ] };
B. 配置到這步後,就能知足基本開發了。試用以後,這時候對本身提出了幾個問題:
命名css,開發的時候能不能不用擔憂命名衝突的問題。
css中引入圖片後,編譯失敗問題。
第三方插件 加載效果pace組件,引入問題。
如今文件過大,有根據路由按需加載需求。
針對上面4個問題,從新配置:
第2個和3個解決方案一致:即聲明別名
resolve: { extensions: ['.js', '.jsx', '.less', '.css', '.png', '.jpg', '.svg', '.gif', '.eot'], alias: { pace: path.resolve(ROOT_PATH, '../src/plugins/pace/index.js'), ImagesPath: path.resolve(ROOT_PATH, '../src/') } }
當中第3個問題,網上找了好多資料,都沒有結果,後來請教了前端羣的同行,才解決該問題。
解決第1個問題過程當中,我學習到了cssModule的概念,一開始菜鳥還很差理解,實踐了後,還真是個好東西。
{ test: /\.(css|less)$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: [ 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]', 'less-loader' ] }), exclude: /node_modules/ },
只要css-loader啓動modules就行了。爲了支持 react,引入了 react-css-modules 依賴包。
網易雲免費體驗館,0成本體驗20+款雲產品
更多網易研發、產品、運營經驗分享請訪問網易雲社區。
相關文章:
【推薦】 HBase原理–全部Region切分的細節都在這裏了
【推薦】 6本互聯網技術暢銷書免費送(數據分析、深度學習、編程語言)!