1. 程式人生 > >react 腳手架搭建

react 腳手架搭建

package.json


{
  "name": "",  
  "version": "1.0.0",  //這是必須配置的
  "description": "",  
  "main": "index.js",
  "scripts": {
    "test": "",
    "watch-client": "",
    "start-prod": "",
    "start-dev-api": "",
    "start": ""
  },
  "repository": {
    "type": "git",
    "url": ""
  },
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/issues"
  },
  "homepage": "https://github.com/#readme",
  "dependencies": {
    "antd": "^2.13.1",    //螞蟻
    "axios": "^0.16.2",    //https://www.kancloud.cn/yunye/axios/234845
    "bluebird": "^3.5.0",  
    "body-parser": "^1.18.0",
    "compression": "^1.7.0",
    "connect-history-api-fallback": "^1.3.0",
    "cookie-parser": "^1.4.3",
    "cookies": "^0.7.1",
    "dateformat": "^3.0.2",
    "echarts-for-react": "^2.0.0",
    "express": "^4.15.4",
    "express-session": "^1.15.5",
    "http-proxy": "^1.16.2",
    "markdown": "^0.5.0",
    "mongoose": "^4.11.11",
    "qs": "^6.5.1",
    "react": "^15.6.1",
    "react-addons-pure-render-mixin": "^15.6.0",
    "react-dom": "^15.6.1",
    "react-helmet": "^5.2.0",
    "react-redux": "^5.0.6",
    "react-router": "^4.2.0",
    "react-router-dom": "^4.2.2",
    "react-slick": "^0.15.4",
    "redux": "^3.7.2",
    "redux-saga": "^0.15.6"
  },
  "devDependencies": {
    "autoprefixer": "^7.1.4",
    "babel-cli": "^6.26.0",
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-plugin-import": "^1.4.0",
    "babel-plugin-react-transform": "^2.0.2",  //代替react-hot-loader?沒用到
    "babel-plugin-transform-class-properties": "^6.24.1",   //看不懂,用就是了
    "babel-plugin-transform-remove-console": "^6.8.5",  //這個也沒用到
    "babel-plugin-transform-runtime": "^6.23.0", //墊子,不管,用就是了
    "babel-polyfill": "^6.26.0",
    "babel-preset-env": "^1.6.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-react-hmre": "^1.1.1",  讓babel知道HMR(熱替換)? 好像沒用到
    "babel-preset-react-optimize": "^1.0.1",
    "babel-preset-stage-0": "^6.24.1",
    "babel-register": "^6.26.0",
    "babel-runtime": "^6.26.0",
    "concurrently": "^3.5.0",
    "cross-env": "^5.0.5",
    "css-loader": "^0.28.7",
    "file-loader": "^0.11.2",
    "install": "^0.10.1",
    "less": "^2.7.2",
    "less-loader": "^4.0.5",
    "node-loader": "^0.6.0",
    "node-sass": "^4.5.3",
    "npm": "^5.4.1",
    "postcss-loader": "^2.0.6",
    "react-hot-loader": "^3.0.0-beta.6",
    "sass-loader": "^6.0.6",
    "style-loader": "^0.18.2",
    "uglifyjs-webpack-plugin": "^1.1.6",
    "url-loader": "^0.5.9",
    "webpack": "^3.5.6",
    "webpack-dev-middleware": "^1.12.0",  
    "webpack-hot-middleware": "^2.19.1",
    "webpack-isomorphic-tools": "^3.0.3",
    "webpack-module-hot-accept": "^1.0.5"    //熱更新外掛
  }
}




//webpack.config.js


const pathLib = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');     
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
const ExtractText = require('extract-text-webpack-plugin');
const config = require('./config/config');


const ROOT_PATH = pathLib.resolve(__dirname);
const ENTRY_PATH = pathLib.resolve(ROOT_PATH, 'app');
const OUTPUT_PATH = pathLib.resolve(ROOT_PATH, 'build');
console.log(pathLib.resolve(ENTRY_PATH, 'index.js'));


module.exports = {
    entry: {
        index: [
            'react-hot-loader/patch',
            `webpack-hot-middleware/client?path=http://${config.host}:${config.port}/__webpack_hmr`,
            'babel-polyfill',
            pathLib.resolve(ENTRY_PATH, 'index.js')
        ],
        vendor: ['react', 'react-dom', 'react-router-dom']
    },
    output: {
        path: OUTPUT_PATH,
        publicPath: '/',
        filename: '[name]-[hash:8].js',
        chunkFilename: '[name].[chunkhash:5].chunk.js',
    },
    devtool: 'false',
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                use: [‘webpack-module-hot-accept’//熱更新,'babel-loader']
            },
            {
                test: /\.css$/,
                exclude: /node_modules/,
                use:ExtractText.extract({
                    fallback: "style-loader",
                    use: [
                        {
                            loader: 'css-loader',
                            options: {
                                modules: true,
                                localIdentName: '[path][name]-[local]-[hash:base64:5]',
                                importLoaders: 1
                            }
                        },
                        'postcss-loader'
                    ]
                })   可以將css從js中提取出來,不過好像會報錯
            },
            {
                test: /\.css$/,
                include: /node_modules/,
                use: ['style-loader',
                    {
                        loader: 'css-loader'
                    },
                    'postcss-loader'
                ]
            },
            {
                test: /\.less$/,
                use: ["style-loader", 'css-loader', "postcss-loader", "less-loader"]
            },
            {
                test: /\.(png|jpg|gif|JPG|GIF|PNG|BMP|bmp|JPEG|jpeg)$/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 8192
                        }
                    }
                ]
            },
            {
                test: /\.(eot|woff|ttf|woff2|svg)$/,
                use: 'url-loader'
            }
        ]
    },
    plugins: [
        new UglifyJSPlugin(),   開發環境時慎用,因為他會壓縮程式碼,可能看不到錯誤具體出現在哪裡
        new ProgressBarPlugin(),
        new webpack.optimize.AggressiveMergingPlugin(),//改善chunk傳輸
        new webpack.optimize.ModuleConcatenationPlugin(),//只要能縮小打包檔案就足夠了,並且沒有其他影響
        new webpack.HotModuleReplacementPlugin(),
        new webpack.DefinePlugin({
            "progress.env.NODE_ENV": JSON.stringify('development')
        }),
        new HtmlWebpackPlugin({
            title: "Zp's Blog",
            showErrors: true,
        }),
        new webpack.NoEmitOnErrorsPlugin(),//保證出錯時頁面不阻塞,且會在編譯結束後報錯
        new webpack.HashedModuleIdsPlugin(),//用 HashedModuleIdsPlugin 可以輕鬆地實現 chunkhash 的穩定化
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            minChunks: function (module) {
                return module.context && module.context.indexOf('node_modules') !== -1;
            }
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: "manifest"
        })
    ],
    resolve: {
        extensions: ['.js', '.json', '.sass', '.scss', '.less', 'jsx']
    }
};




server.js


import path from 'path'
import Express from 'express'
import favicon from 'serve-favicon'
import httpProxy from 'http-proxy'
import compression from 'compression'
import connectHistoryApiFallback from 'connect-history-api-fallback'
import config from '../config/config'


if(process.env.NODE_EVN!=='production'){
    const Webpack = require('webpack');
    const WebpackDevMiddleware = require('webpack-dev-middleware');
    const WebpackHotMiddleware = require('webpack-hot-middleware');
    const webpackConfig = require('../webpack.dev');


    const compiler = Webpack(webpackConfig);


    app.use(WebpackDevMiddleware(compiler, {
        publicPath: '/',
        stats: {colors: true},
        lazy: false,
        watchOptions: {
            aggregateTimeout: 300,
            poll: true
        },
    }));
    app.use(WebpackHotMiddleware(compiler));
}






經常使用react所以需要配置babel


一、配置檔案.babelrc
Babel的配置檔案是.babelrc,存放在專案的根目錄下。使用Babel的第一步,就是配置這個檔案。
該檔案用來設定轉碼規則和外掛,基本格式如下。


{
  "presets": [],
  "plugins": []
}
presets欄位設定轉碼規則,官方提供以下的規則集,你可以根據需要安裝。


# ES2015轉碼規則
$ npm install --save-dev babel-preset-es2015


# react轉碼規則
$ npm install --save-dev babel-preset-react


# ES7不同階段語法提案的轉碼規則(共有4個階段),選裝一個
$ npm install --save-dev babel-preset-stage-0
$ npm install --save-dev babel-preset-stage-1
$ npm install --save-dev babel-preset-stage-2
$ npm install --save-dev babel-preset-stage-3
然後,將這些規則加入.babelrc。


  {
    "presets": [
      "es2015",
      "react",
      "stage-0",
      "env"
    ],
    "plugins": []
  }
注意,以下所有Babel工具和模組的使用,都必須先寫好.babelrc。


{
  "presets": ["es2015","react","stage-0","env"],
  "plugins": ["react-hot-loader/babel",["import", { "libraryName": "antd", "style": true }],"transform-runtime","transform-class-properties"],
  "env": {
    "production":{
      "preset":["react-optimize"]
    }
  }
}




postcss.config.js


module.export = {
    plugins:[
        require('autoprefixer')({browsers:'last 2 versions'})
    ]
};