react技術棧實踐(1)

本文來自網易雲社區css

做者:汪洋html


背景

最近開發一個全新AB測試平臺,思考了下正好可使用react技術開發。前端


實踐前技術準備

首先遇到一個概念,redux。這貨還真很差理解,大致的理解:Store包含全部數據,視圖觸發一個Action,Store收到Action後,返回一個新的 State,這樣視圖就發生變化,State計算過程叫作 Reducer,Reducer其實就是一個處理數據的函數,接受 Action和 當前State做爲參數,返回一個新的 State。
明白這個後,就能夠開始實踐了。node


搭建平臺的腳手架

對於我這方面沒搞過的菜鳥,還真是不容易。接下來講下做爲新手如何實踐的。react

  1. 第一步:依賴包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

  2. 第二步: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. 配置到這步後,就能知足基本開發了。試用以後,這時候對本身提出了幾個問題: 

  1. 命名css,開發的時候能不能不用擔憂命名衝突的問題。

  2. css中引入圖片後,編譯失敗問題。

  3. 第三方插件 加載效果pace組件,引入問題。

  4. 如今文件過大,有根據路由按需加載需求。 


針對上面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本互聯網技術暢銷書免費送(數據分析、深度學習、編程語言)!

相關文章
相關標籤/搜索