• typescript+react+antd基础环境搭建


    typescript+react+antd基础环境搭建(包含样式定制)

    
    // 具体配置可以看上面的链接 这里module moduleResolution的配置都会影响到antd的显示
    // allowSyntheticDefaultImports  是antd官网给的配置 必须加上
    {
        "compilerOptions": {
            "outDir": "./dist/",
            "sourceMap": false,
            "noImplicitAny": false,
            "module": "es6",
            "target": "es5",
            "jsx": "preserve",
            "moduleResolution": "node",
            "forceConsistentCasingInFileNames": false,
            "allowJs": true,
            "allowSyntheticDefaultImports": true,
            "lib": [
                "es5", 
                "dom",
                "dom.iterable",
                "es2015"
            ]
        },
        "include": [
            "./src/**/*"
        ]
    }
    
    • package.json 配置
    
    // 其中很多配置是用来做antd样式定制的
    // concurrently 是用来将命令连接起来执行的 Run multiple commands concurrently
    {
      "name": "power3",
      "version": "1.0.0",
      "description": "typescript && react for power3",
      "main": "index.js",
      "scripts": {
        "build": "webpack --progress --colors",
        "start": "concurrently "node ./server/server.js" " npm run dev "",
        "dev": "webpack-dev-server --progress --colors -p -d"
      },
      "author": "",
      "license": "ISC",
      "dependencies": {
        "antd": "^2.13.6",
        "css-loader": "^0.28.7",
        "immutable": "^3.8.2",
        "md5": "^2.2.1",
        "react": "^15.5.4",
        "react-dom": "^15.5.4",
        "react-hot-loader": "^3.1.1",
        "react-router": "^4.2.0",
        "react-router-dom": "^4.2.2"
      },
      "devDependencies": {
        "@types/node": "^8.0.34",
        "@types/react": "^16.0.10",
        "@types/react-dom": "^16.0.1",
        "@types/react-router": "^4.0.15",
        "@types/react-router-dom": "^4.0.8",
        "awesome-typescript-loader": "^3.2.3",
        "babel-core": "^6.26.0",
        "babel-loader": "^7.1.2",
        "babel-plugin-import": "^1.6.2",
        "babel-preset-env": "^1.6.1",
        "babel-preset-react": "^6.24.1",
        "babel-preset-stage-0": "^6.24.1",
        "concurrently": "^3.4.0",
        "extract-text-webpack-plugin": "^2.1.0",
        "html-webpack-plugin": "^2.30.1",
        "less": "^2.7.2",
        "less-loader": "^4.0.5",
        "less-vars-to-js": "^1.2.0",
        "source-map-loader": "^0.2.2",
        "style-loader": "^0.19.0",
        "typescript": "^2.5.3",
        "url-loader": "^0.5.8",
        "webpack": "^2.3.3",
        "webpack-dev-server": "^2.4.2",
        "webpack-hot-middleware": "^2.20.0"
      }
    }
    
    
    • routes.tsx页面

    该页面主要用来配置路由 指定登录页面
    推荐使用react-router-dom 里面的各种接口直接继承感觉很方便

    
    /**
     * 路由写到此处 页面一般会有层级关系 此处json对象是按照业务写成层级关系
     * 第一种做法是 处理成 平级的路由
     * 第二种是 根据业务的层级关系渲染出符合业务的相应导航
     * 此处两种都导出 然后在index.tsx中可以两种都试一下
     */
    
    import {RouteProps} from 'react-router-dom'
    
    import Apple from './components/fruits/Apple'
    import Banana from './components/fruits/banana'
    
    import Cabbage from './components/vegetables/cabbage'
    import Radish from './components/vegetables/radish'
    
    interface PowerRouteProps extends RouteProps{
        name:string;
    }
    
    export const _routes=[
        {
            id:'fruits',
            name:'水果',
            routes:[
                {
                    name:'苹果',
                    path:'/apple',
                    component:Apple
                },
                {
                    name:'香蕉',
                    path:'/banana',
                    component:Banana
                }
            ]
        },
        {
            id:'vegetables',
            name:'蔬菜',
            routes:[
                {
                    name:'白菜',
                    path:'/cabbage',
                    component:Cabbage
                },
                {
                    name:'萝卜',
                    path:'/radish',
                    component:Radish
                }
            ]
        }
    ];
    // 此处变量我之前使用 routes 命名 结果在index.tsx引入时(import {routes} from './routes') 直接报错
    // 注意导出变量名和文件名不能一样
    export const maproutes = _routes.reduce((ary:PowerRouteProps[],cur:any)=>{
        return ary.concat(cur.routes||cur)
    },[]).filter(x=>x.path && x.path!=='');
    
    • 简单的业务组件(只为了说明)

    其他的组件可以在github上看

    
    // ./components/vegetables/cabbage 
    
    import * as React from 'react'
    
    export default class Cabbage extends React.Component{
        render(){
            return (<p>You need to eat cabbage</p>)
        }
    }
    
    • 入口文件index.tsx

    此处写了两种导航 一种有submenu 一种是使用plain数据直接将所有路由列出

    
    import * as React from 'react'
    import * as ReactDOM from 'react-dom'
    import {HashRouter, Route, Switch, Link, BrowserRouter} from 'react-router-dom'
    // 提供antd的本地语言支持
    import {LocaleProvider, Menu} from 'antd'
    const MenuItem = Menu.Item;
    const SubMenu = Menu.SubMenu;
    
    import {maproutes,_routes} from './routes'
    // plain 路由
    class Navigation extends React.Component {
        render() {
            return (
                <Menu>
                    {maproutes.map(route => {
                        return (
                            <MenuItem key={route.path}>
                                <Link to={route.path} key={`route-link-${route.path}`}>{route.name}</Link>
                            </MenuItem>
                        )
                    })}
                </Menu>
            )
        }
    }
    // 有层级关系的路由
    class Navigations extends React.Component {
        render() {
            return (
                <Menu style={{200}} mode="inline">
                    {_routes.map(routes=>{
                        return (
                        <SubMenu key={routes.id} title={routes.name}>
                            {routes.routes.map(route=>{
                                return (
                                    <MenuItem key={`route-${route.path}`}>
                                        <Link to={route.path} key={`route-link-${route.path}`}>{route.name}</Link>
                                    </MenuItem>
                                )
                            })}
                        </SubMenu>)
                    })}
                </Menu>
            )
        }
    }
    
    class NotFoundView extends React.Component {
        render() {
            return (
                <div className="http-404">
                    <h2 className="text-info">功能尚未开发完毕</h2>
                    <h3 className="text-danger">Page not found</h3>
                </div>
            );
        }
    }
    
    const Router = () => (
        <BrowserRouter>
            <Switch>
                {maproutes.map(route => {
                    // return <Route path={route.path} key={`route-path-${route.path}`} location={route.location} component={route.component}/>
                    return <Route path={route.path} key={`route-${route.path}`} component={route.component}/>
                })}
                <Route path="/" exact component={Navigations}/>
                <Route component={NotFoundView}/>
            </Switch>
        </BrowserRouter>
    )
    
    ReactDOM.render(
        <Router/>, document.getElementById('app'));
    

    创建.babelrc文件
    在终端(ctrl+`)中输入 type null>.babelrc

    .babelrc文件

    plugins的配置是为了让antd的样式生效

    
    {
        "presets": [
          ["env"],
          "stage-0",
          "react"
        ],
        "plugins": [
            "react-hot-loader/babel",
            ["import", { "libraryName": "antd","style": true}]
        ]
      }
    
    • 最后一步 webpack.config.js文件编写
    
    const webpack = require('webpack');
    const ExtractTextPlugin = require('extract-text-webpack-plugin');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const path = require('path');
    const fs = require('fs');
    const lessToJs = require('less-vars-to-js');
    
    // 获取自己定义的要覆盖antd默认样式的文件
    const themeVariables = lessToJs(fs.readFileSync(path.join(__dirname, './src/assets/style/themes.less'), 'utf8'));
    
    module.exports = {
        entry: "./src/index.tsx",
        output: {
            filename: "bundle.js",
            path: __dirname + "/dist"
        },
    
        // Enable sourcemaps for debugging webpack's output.
        devtool: "cheap-moudle-source-map",
    
        resolve: {
            // Add '.ts' and '.tsx' as resolvable extensions.
            extensions: [".ts", ".tsx", ".js", ".json"]
        },
        devServer: {
            port: 8003,
            hot: true,
            // historyApiFallback: true,
            historyApiFallback: {
                index: '/react.min.js'
            },
            contentBase: path.resolve(__dirname, 'dist'),
            publicPath: '/'
        },
        module: {
            rules: [
                // All files with a '.ts' or '.tsx' extension will be handled by
                // 'awesome-typescript-loader'.
                {
                    test: /.(tsx|ts)?$/,
                    use: [
                        {
                            loader: 'react-hot-loader/webpack'
                        }, {
                            loader: 'babel-loader'
                        }, {
                            loader: 'awesome-typescript-loader'
                        }
                    ]
                },
    
                // All output '.js' files will have any sourcemaps re-processed by
                // 'source-map-loader'.
                {
                    enforce: "pre",
                    test: /.js$/,
                    loader: "babel-loader",
                    exclude: /node_modules/
                }, {
                    test: /.less$/,
                    use: [
                        {
                            loader: "style-loader"
                        }, {
                            loader: "css-loader"
                        }, {
                            loader: "less-loader",
                            options: {
                                modifyVars: themeVariables
                            }
                        }
                    ]
                }, {
                    test: /.css$/,
                    use: ExtractTextPlugin.extract({fallback: 'style-loader', use: 'css-loader', publicPath: '/'})
                }, {
                    test: /.(png|jpg|jpeg|gif|svg)$/,
                    loader: 'url-loader?limit=8192&name=[name].[ext]&publicPath='
                }
            ]
        },
        // When importing a module whose path matches one of the following, just assume
        // a corresponding global variable exists and use that instead. This is
        // important because it allows us to avoid bundling all of our dependencies,
        // which allows browsers to cache those libraries between builds.
        externals: {
            // "react": "React",
            // "react-dom": "ReactDOM"
        },
        plugins: [
            new HtmlWebpackPlugin({
                template: './src/index.html',
                title: 'hello ts&react',
                inject: false,
                minify: {
                    removeComments: true,
                    collapseWhitespace: true
                },
                chunksSortMode: 'dependency'
            }),
            new ExtractTextPlugin({filename: '[name].css', allChunks: true}),
            new webpack.HotModuleReplacementPlugin()
        ]
    };
    
    // 此处是借鉴同事的 啊哈哈哈
    const os = require('os');
    console.log(`############################################################################`);
    console.log(`##         os: ${os.type()} ${os.arch()} ${os.release()}`);
    console.log(`##        ram: ${ (os.freemem() / 1024 / 1024 / 1024) < 1
        ? (os.freemem() / 1024 / 1024).toFixed(0) + 'MB'
        : (os.freemem() / 1024 / 1024 / 1024).toFixed(2) + 'GB'}`);
    console.log(`##       time: ${new Date()}`);
    console.log(`############################################################################`);
    

    项目地址

    来源:https://segmentfault.com/a/1190000011721098

  • 相关阅读:
    ios特性访问器方法(setter和getter)
    JavaScript文本收缩展开 showdetail
    MSClass (Class Of Marquee Scroll通用不间断滚动JS封装类) Ver 1.65
    拖动层 拖动div 封装js 貌似不兼容FF,郁闷
    cookie中存储json
    页面get post等查看
    瑞星杀毒软件2010年1月11日8:29:28 【免费】
    div两侧的boder断开 消失 奇怪
    用来武装Firebug的十四款Firefox插件
    在内容页中调用母版页控件、响应控件消息(用户控件、服务器控件有所不同)
  • 原文地址:https://www.cnblogs.com/lovellll/p/10162102.html
Copyright © 2020-2023  润新知