美文网首页
H5入门01-React+dva+webpack搭建项目框架

H5入门01-React+dva+webpack搭建项目框架

作者: 最爱的火 | 来源:发表于2019-02-26 15:26 被阅读26次

    H5入门01-dva+webpack搭建框架

    对于移动端开发者而言,开发H5一般使用 React +Dvajs + Webpack+andt.mobile进行开发,下面就用它们来搭建项目。

    基础框架搭建

    dva框架用于路由、架构、异步操作和网络请求。使用dva new创建项目时,默认使用roadhog进行打包和开启服务。

    webpack用于打包,使用webpack-dev-server来开启服务。相比roadhog,更加稳定,但是配置更加复杂。如果使用roadhog打包,就不需要安装webpack。

    andt.mobile是阿里的ui框架,封装了很多常用的ui组件,功能强大,但是使用有点复杂。

    注意:需要先安装npm和python。

    参考文章:http://www.cnblogs.com/axel10/p/8973783.html

    1 安装dva框架

    截止 2017.1,最流行的社区 React 应用架构方案如下。

    缺点:要引入多个库,项目结构复杂。

    dva = React-Router + Redux + Redux-saga, 是对上面三个 React 工具库的封装,还额外内置了 fetch,简化了 API,让开发 React 应用更加方便和快捷。

    安装 dva-cli

    通过 npm 安装 dva-cli 并确保版本是 0.9.1 或以上。

    $ npm install dva-cli -g
    $ dva -v
    dva-cli version 0.9.1
    

    创建新应用

    安装完 dva-cli 之后,就可以在命令行里访问到 dva 命令。现在,你可以通过 dva new 创建新应用。

    $ dva new dva-quickstart
    

    这会创建 dva-quickstart 目录,包含项目初始化目录和文件,并提供开发服务器、构建脚本、数据 mock 服务、代理服务器等功能。

    然后我们 cd 进入 dva-quickstart 目录,并启动开发服务器:

    $ cd dva-quickstart
    $ npm start
    

    几秒钟后,你会看到以下输出:

    Compiled successfully!
    
    The app is running at:
    
      http://localhost:8000/
    
    Note that the development build is not optimized.
    To create a production build, use npm run build.
    

    在浏览器里打开 http://localhost:8000 ,你会看到 dva 的欢迎界面。

    2 安装webpack

    如果使用默认的roadhog打包,就跳过此步骤。

    如果是webpack打包,就可以先删除roadhog的配置,再安装webpack。

    • 删除.webpackrc
    • 删除.roadhogrc.mock.js
    • 删除roadhog:npm uninstall --save-dev roadhog

    基本配置

    安装框架

    //安装webpack框架
    npm install --save-dev webpack webpack-cli 
    //安装webpack服务器,用于本地调试
    npm install --save-dev webpack-dev-server
    //安装本地打包框架
    npm install --save-dev lodash 
    //安装css样式加载框架
    npm install --save-dev style-loader css-loader
    //安装scss样式加载框架
    npm install --save-dev node-sass sass-loader
    //安装文件加载框架
    npm install --save-dev file-loader
    //安装html处理框架
    npm install --save-dev html-webpack-plugin
    //安装文件清理框架
    npm install --save-dev clean-webpack-plugin 
    //安装样式分离框架,用于将样式文件单独打包,提高加载速度。注意直接安装extract-text-webpack-plugin会发生兼容性问题。
    npm install --save-dev extract-text-webpack-plugin@next
    //安装webpack合并框架,用来合并webpack的配置文件
    npm install --save-dev webpack-merge
    //用来拷贝文件
    npm install --save-dev copy-webpack-plugin
    //用来压缩文件
    npm install --save-dev uglifyjs-webpack-plugin
    

    webpack.base.config.js

    const path = require('path');
    const webpack = require('webpack');
    
    //配置参数
    var config = {
      //入口文件
      entry: './src/index.js',
      //出口文件
      output: {
        //name是入口文件名,默认为main,当存在多个入口文件是需要使用
        filename: 'main.js',
        //__dirname为系统变量,代表当前目录名
        path: path.resolve(__dirname, 'dist'),
        //指定所有资源的基础路径,默认为空,一般不需要指定
        publicPath: '',
      },
      //用来追踪源代码,因为webpack打包源代码时,可能会很难追踪到错误和警告在源代码中的原始位置
      devtool: 'inline-source-map',
      //配置webpack服务器的参数
      devServer: {
        //热替换,当本地文件更新后,浏览器页面自动刷新
        hot: true,
        //设置代理
        proxy: {
          //对以'/open/api/weather/'开头的请求进行代理
          '/open/api/weather/*': {
            //需要代理的地址
            target: 'https://www.sojson.com',
            // 允许https请求
            secure: true,
            //允许跨域
            changeOrigin: true
          }
        }
      },
      //加载模块
      module: {
        //加载规则
        rules: [
          {
            //加载js文件
            test: /\.jsx?$/,
            //指定加载器
            use: ['babel-loader'],
            //指定需要加载的目录
            include: path.join(process.cwd(), 'src')
          },
          {
            test: /\.(png|svg|jpg|gif)$/,
            use: ['file-loader?limit=8192&name=image/[name].[hash:4].[ext]'],
          },
          {
            test: /\.(woff|woff2|eot|ttf|otf)$/,
            use: ['file-loader?limit=8192&name=image/[name].[hash:4].[ext]']
          }
        ]
      },
      plugins: [
        //热替换插件
        new webpack.HotModuleReplacementPlugin(),
        //定义全局变量,webpack编译后生效。_ENV_:将_ENV_定为全局变量,开发时会有警告。'window._ENV_':在window对象中定义_ENV_属性,开发时没警告。
        new webpack.DefinePlugin({_ENV_: JSON.stringify({isMock: false}), 'window._ENV_': JSON.stringify({isMock: false})}),
      ]
    }
    
    module.exports = config;
    
    

    package.json

    {
        ...
        "scripts": {
         "start": "webpack-dev-server --hot --open --port 1111 --config  webpack.dev.config.js",
         "build": "webpack --config webpack.dev.config.js",
        },
        ...
    }
    

    注意:如果使用roadhog打包,会自动识别webpack.config.js文件,并且要求webpack.config.js返回一个函数。

    支持非ES5语法

    安装框架:

    //安装babel转码器
    npm install --save-dev @babel/core
    //用来转换ES6中新的API。babel默认只转换新的JS语法,比如Symbol、Promise等全局对象不会转码
    npm install --save @babel/polyfill
    //安装babel转码器的加载器
    npm install --save-dev babel-loader
    //用来支持react框架
    npm install --save-dev @babel/preset-react
    //用来支持ES6语法
    npm install --save-dev @babel/preset-es2015
    //用来支持最新的ES语法
    npm install --save-dev @babel/preset-env
    //用来支持已经正式提案,但是还没正式发版的ES语法。已废弃。
    npm install --save-dev @babel/preset-stage-1
    //用来支持Decorators语法。修饰器(Decorator)是ES7提案中的一个函数,用来修改类的行为。
    npm install --save-dev @babel/plugin-proposal-decorators
    //用来支持babel-runtime语法。@babel/runtime用于避免重复编译文件。
    npm install --save-dev @babel/plugin-transform-runtime
    //用于按需加载第三方库中的组件,而不是加载整个库
    npm install --save-dev babel-plugin-import
    //用于异步加载文件。在运行时加载,而不是编译时加载
    npm install --save-dev @babel/plugin-syntax-dynamic-import
    //用于在class中声明属性
    cnpm install --save-dev babel-plugin-transform-class-properties
    

    注意:babel7.0之前,使用babe-命名,7.0以后,使用@babel/命名。

    .babelrc

    {
      //预设转码,用来将非ES6语法转换为ES6语法
      "presets": [
        "react",
        "env",
        "stage-1"
      ],
      "plugins": ["transform-decorators-legacy" ,"transform-runtime"]
    }
    

    babel/polyfill的使用:

    • 方法一:在头部js中:require("@babel/polyfill")import "@babel/polyfill"

    • 方法二:在webpack.config.js中添加:

      module.exports = {
        entry: ['@babel/polyfill','./src/index.js']
      };
      

    开发配置

    webpack.dev.config.js

    const baseWebpackConfig = require('./webpack.base.config.js');
    const merge = require('webpack-merge');
    
    //开发环境配置参数
    var config = {
      //加载模式:开发模式或生产模式
      mode: "development",
      //加载模块
      module: {
        //加载规则
        rules: [
          {
            test: /\.s?css$/,
            //将样式文件打包到js中
            use: ['style-loader', 'css-loader', 'sass-loader'],
          },
        ]
      },
    };
    
    module.exports = merge(baseWebpackConfig, config);
    

    webpack把js文件打包,需要一个入口页来加载:index.html,默认位于项目的根目录。

    <!doctype html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>CommonH5</title>
    </head>
    <body>
    <div id="root"></div>
    <!--导入打包后生成的js文件,注意引用路径要与webpack.config.js中配置的出口文件保持一致-->
    <script src="main.js">
    </script>
    </body>
    </html>
    

    生产配置

    webpack.prod.config.js

    const baseWebpackConfig = require('./webpack.base.config.js');
    const merge = require('webpack-merge');
    const path = require('path');
    const webpack = require('webpack');
    const CopyWebpackPlugin = require('copy-webpack-plugin');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
    const ExtractTextPlugin = require('extract-text-webpack-plugin');
    
    //生产环境配置文件
    var config = {
      //指定生产环境
      mode: "production",
      //加载模块
      module: {
        //加载规则
        rules: [
          {
            test: /\.s?css$/,
            //将样式文件与js分离,提高加载速度
            use: ExtractTextPlugin.extract({fallback: 'style-loader', use: ['css-loader', 'sass-loader']})
          },
        ]
      },
      plugins: [
        //压缩插件
        new UglifyJsPlugin({
          uglifyOptions: {
            compress: {
              warnings: false
            }
          },
          parallel: true
        }),
        //html加载插件
        new HtmlWebpackPlugin({
          filename: path.join(process.cwd(), 'dist/index.html'),
          template: 'index-build.html',
          inject: true,
          hash: true,
          minify: {
            removeComments: true,
            collapseWhitespace: true,
            removeAttributeQuotes: true
          },
          // necessary to consistently work with multiple chunks via CommonsChunkPlugin
          chunksSortMode: 'dependency'
        }),
        //分离样式插件
        new ExtractTextPlugin({filename: 'main.css'}),
        // keep module.id stable when vendor modules does not change
        new webpack.HashedModuleIdsPlugin(),
        //用来复制文件
        new CopyWebpackPlugin([]),
      ]
    }
    
    module.exports = merge(baseWebpackConfig, config);
    

    生产打包时,需要在dist目录生成一个index.html文件,生成这个文件需要配置一个模板文件:index-duild.html

    <!doctype html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>CommonH5</title>
    </head>
    <body>
    <div id="root"></div>
    </body>
    </html>
    

    图片引用

    使用webpack打包时,图片不能直接传路径。

    //这样webpack打包时,会解析成http://localhost:1111/assets/yay.jpg,从而获取失败
    <img src='../assets/yay.jpg'/>
    

    有两种方式:

    1.使用url函数:只能在.scss中使用

    .float1 {
        background: url(../../assets/yay.jpg) no-repeat center 0;
    }
    

    2.使用requrie函数:在.scss和.js中都能使用

    <img src={require('../assets/yay.jpg')}/>
    

    3 安装antd-mobile

    通过 npm 安装 antd-mobilebabel-plugin-importbabel-plugin-import 是用来按需加载 antd 的脚本和样式的。

    npm install --save antd-mobile
    npm install --save-dev babel-plugin-import
    

    如果使用roadhog打包,编辑 .webpackrc,使 babel-plugin-import 插件生效。

    {
      "extraBabelPlugins": [
        ["import", { "libraryName": "antd-mobile", "libraryDirectory": "es", "style": "css" }]
      ]
    }
    

    如果使用webpack打包,编辑 .babelrc,使 babel-plugin-import 插件生效。并且打包css文件时,不要排除node_modules,否则antd-mobile的css无法生效。

    {
      ...
      "plugins": [
        ["import", { "libraryName": "antd-mobile", "libraryDirectory": "es", "style": "css" }],
        ...
      ]
    }
    

    4 调试与打包

    调试:npm start

    打包:npm build。

    打包后,会在dist目录生成所有的文件,包含一个index.html、一个main.css、n个图片等资源、n个js文件。

    注意:使用dva构建项目默认生成的IndexPage.js,引用样式的方式在webpack中不支持,应改为:

    import './IndexPage.scss';
    ...
    <div className={'normal'}>
    

    第一个页面

    1 简单页面

    页面统一在src/routes目录进行开发,一个页面由一个js文件和一个scss(或css)文件组成。

    首先写js文件。

    Demo.js

    import React from 'react';
    import {connect} from 'dva'
    import {queryDemoData} from '../services/serverDemo'
    import {routerRedux} from 'dva/router';
    import './Demo.scss'
    
    //基础样式名
    const baseStyle = 'demo';
    //数据源
    var dataSource = null;
    
    /**
     * Demo页面
     */
    @connect(() => ({}))
    export default class Demo extends React.Component {
    
      //构造函数
      constructor(props) {
        super(props);
        //使用state保存dataSource
        this.state = {
          dataSource: dataSource,
        }
      }
    
      //界面渲染之前的回调函数
      componentWillMount() {
        // this.getTestData();
        this.getRealData();
      }
    
      //界面渲染函数
      render() {
        let list = this.renderList();
        return (
          <div className={`${baseStyle}`}>
            {list}
            <button className={`${baseStyle}-button`} onClick={()=>this.onGo()}>页面跳转</button>
          </div>
        )
      }
    
      /**
       * 获取测试数据
       */
      getTestData() {
        dataSource = [
          {
            img: 'https://zos.alipayobjects.com/rmsportal/dKbkpPXKfvZzWCM.png',
            text: '6217000011112666'
          },
          {
            img: 'https://zos.alipayobjects.com/rmsportal/XmwCzSeJiqpkuMB.png',
            text: '6217000011112777'
          }
        ];
        this.setState({dataSource: dataSource});
      }
    
      /**
       * 获取真实数据
       */
      getRealData() {
        queryDemoData().then((result)=> {
          console.log(result);
          //如果请求成功,就刷新页面
          if (result.data.code == "000000") {
            dataSource = result.data.data.list;
          } else {
            dataSource == null;
          }
          this.setState({dataSource: dataSource});
        }, (error)=> {
          console.log(error);
        });
      }
    
      /**
       * 生成列表
       */
      renderList() {
        let data = this.state.dataSource;
        if (!data || !data.length) {
          return null;
        }
    
        let items = [];
        for (let i = 0; i < data.length; i++) {
          let itemData = data[i];
          let key = `ListItem${i}`;
          let item =
            <li key={key} className={`${baseStyle}-list-row`}>
              <div className={`${baseStyle}-list-row-content`}>
                <img src={`${itemData.img}`} className={`${baseStyle}-list-row-img`}/>
                <span className={`${baseStyle}-list-row-text`}>{itemData.text}</span>
              </div>
              <div className={`${baseStyle}-list-separator`}/>
            </li>;
          items.push(item);
        }
    
        return (
          <ul className={`${baseStyle}-list`}>
            {items}
          </ul>
        );
      }
    
      /**
       * 页面跳转
       */
      onGo() {
        //指定需要跳转的页面,页面路径为router.js中配置的path
        let action = routerRedux.push('/');
        //添加@connect后,redux会给页面添加dispatch属性,通过dispatch来分发action
        this.props.dispatch(action);
      }
    }
    

    注意:如果React.Component写成React.componentReact.createComponent,则需要添加constructor(props) {super(props);},否则webpack打包后会报错。

    然后,写样式文件。创建样式时,统一以文件名作为所有样式的开头(通过&连接),这样可以避免样式被覆盖。

    Demo.scss

    .demo {
      width: 100%;
      height: 100%;
      background-color: #F5F5F5;
      overflow: auto;
    
      //代表.css-demo-list.使用&连接上层样式名
      &-list {
        //布局方式
        display: flex;
        //flex方向.row代表水平排列,column代表垂直排列
        flex-direction: column;
        width: 100%;
        height: 100%;
        padding: 0px;
        margin: 0px;
    
        &-row {
          display: flex;
          flex-direction: column;
          width: 100%;
          height: 60px;
    
          &-content {
            display: flex;
            flex-direction: row;
            //flex方向的对齐
            justify-content: flex-start;
            //非flex方向的对齐:如果flex是水平的,那么内容垂直居中;如果flex是垂直的,那么内容水平居中;
            align-items: center;
            width: 100%;
            height: 100%;
          }
    
          &-img {
            width: 40px;
            height: 40px;
            margin-left: 10px;
          }
    
          &-text {
            width: 100%;
            margin-left: 10px;
            font-size: 20px;
          }
        }
        //分割线样式
        &-separator {
          width: 100%;
          height: 1px;
          background-color: #E5E5E5;
        }
      }
      &-button {
        width: 100%;
        height: 60px;
        margin: 10px;
        font-size: 20px;
        color: #00aaee;
        background: #FFFFFF;
        border: 1px solid #00aaee;
        border-radius: 4px;
      }
    }
    

    注意:css中属性名没有驼峰式,使用-分开,比如:在style中的borderTop在css中要写成border-top

    最后,配置路由。页面完成后,需要在src/router.js中配置路由

    import React from 'react';
    import {Router, Route, Switch} from 'dva/router';
    import IndexPage from './routes/IndexPage';
    import Demo from './routes/Demo';
    
    function RouterConfig({history}) {
      return (
        <Router history={history}>
          <Switch>
            <Route path="/" exact component={IndexPage}/>
            <Route path="/demo" exact component={Demo}/>
          </Switch>
        </Router>
      );
    }
    
    export default RouterConfig;
    

    然后打开http://localhost:1111/#/demo,就可以访问页面了。

    2 请求本地数据

    dva构建项目时,帮我们封装了网路请求,可以方便的请求本地json数据和网络数据。

    首先,创建本地数据。在mock目录下,创建json文件作为本地数据。

    queryDemoData.json

    {
      "code": "000000",
      "msg": "成功",
      "data": {
        "list": [
          {
            "img": "https://zos.alipayobjects.com/rmsportal/dKbkpPXKfvZzWCM.png",
            "text": "6217000011112666"
          },
          {
            "img": "https://zos.alipayobjects.com/rmsportal/XmwCzSeJiqpkuMB.png",
            "text": "6217000011112777"
          }
        ]
      }
    }
    

    然后,创建请求方法。在src/services下创建请求方法。

    demo.js

    import request from '../utils/request';
    
    export function queryDemoData() {
      //获取本地数据
      return request('/mock/queryDemoData.json');
    }
    

    然后,在页面调用请求方法。

    //界面渲染之前的回调函数
    componentWillMount() {
      this.getRealData();
    }
    
    /**
     * 获取真实数据
     */
    getRealData() {
      queryDemoData().then((result)=> {
        console.log(result);
        //如果请求成功,就刷新页面
        if (result.data.code == "000000") {
          dataSource = result.data.data.list;
        } else {
          dataSource == null;
        }
        this.setState({dataSource: dataSource});
      }, (error)=> {
        console.log(error);
      });
    }
    

    3 请求网络数据

    首先,设置代理。修改webpack.base.config.js的配置,在devServer中设置代理。

    devServer: {
      //热替换,当本地文件更新后,浏览器页面自动刷新
      hot: true,
      //设置代理
      proxy: {
        //对以'/open/api/weather/'开头的请求进行代理
        '/open/api/weather/*': {
          //需要代理的地址
          target: 'https://www.sojson.com',
          // 允许https请求
          secure: true,
          //允许跨域
          changeOrigin: true
        }
      }
    },
    

    设置代理时,需要注意以下规则:

    • proxy的属性代表代理url。请求的url必须以代理url开头,并且不包含host,代理才会生效;
    • 代理url为'*''/'代表代理所有请求,请求的url开头可以省略'/'
    • 代理url必须以'/'开头('*'除外),'/*''/[url]/*'在3.0版本不支持,在4.0版本支持;

    然后,创建请求方法。在src/services下创建请求方法。

    import request from '../utils/request';
    
    export function queryDemoData() {
      //_ENV_是通过webpack.DefinePlugin定义的系统变量,dev代表开发环境,prod代表生产环境.
      if (_ENV_ == 'dev') {
        //获取本地数据
        return request('/mock/queryDemoData.json');
      } else {
        //获取网路数据.需要先在devServer中设置代理.
        return request('/open/api/weather/json.shtml?city=北京');
      }
    }
    

    然后,调用请求方法。同上。

    4 页面跳转

    首先,添加配置。

    import {connect} from 'dva';
    //用于生成页面跳转的action
    import {routerRedux} from 'dva/router';
    
    //添加@connect,参数可为空。用于给页面添加dispatch属性,
    @connect()
    export default class Demo extends React.Component 
    

    注意:connect还可以这样使用:export default connect()(IndexPage);

    然后,跳转页面

    /**
     * 页面跳转
     */
    onGo() {
      //指定需要跳转的页面,页面路径为router.js中配置的path
      let action = routerRedux.push('/');
      //添加@connect后,redux会给页面添加dispatch属性,通过dispatch来分发action
      this.props.dispatch(action);
    }
    

    5 数据传递

    首先,创建model。model用来保存应用的数据,统一在src/models目录下配置。

    modelDemo.js

    export default {
      //model的名字,同时也是他在全局state(应用数据,由多个model组成)上的属性
      namespace: 'demo',
      //当前model的初始值.页面之间是通过model来传递数据的
      state: {demoData: '这是测试Demo',},
      //创建同步修改器,根据action(指令)同步修改当前model的数据,返回修改后的数据
      reducers: {
        /**
         * 同步修改器需要两个参数state和action,state代表当前modal的数据,action指定如何修改当前modal的数据
         * action包含两个属性type和payload
         * type为[model名]/[修改器名],比如:'demo/save'
         * payload为对象,是action传递的数据
         */
        save(state, action) {
          return {...state, ...action.payload};
        },
      },
      //创建异步修改器,根据action(指令)异步修改当前model的数据,返回修改后的数据
      effects: {
        /**
         * 异步修改器使用Generator函数,需要两个参数action和effects,action与同步修改器的action一样,effects定义异步操作
         * effects包含以下属性:
         * call:用于调用异步逻辑,支持promise
         * put:用来发送action(指令),参数为action
         * select:参数为函数(state) => state.demo.demoData,用于从全局state中获取数据
         */
          *fetch({payload}, {call, put, select}) {
          yield call();
          yield put({type: 'save'});
          var data = yield select(state => state.demo.demoData);
        },
      },
    };
    

    然后,应用model。在src/index.js中添加model。

    app.model(require('./models/modelDemo').default);
    

    然后,发送数据。

    onGo() {
        //使用dispacth(action)修改model的数据
        this.props.dispatch({
          //指定model和修改器,格式为[namespace]+[函数名]
          type: 'demo/save',
          //传给修改器的数据
          payload: {
            demoData: '修改后的数据',
          }
        });
    
      //指定需要跳转的页面,页面路径为router.js中配置的path
      let action = routerRedux.push('/');
      //添加@connect后,redux会给页面添加dispatch属性,通过dispatch来分发action
      this.props.dispatch(action);
    }
    

    然后,接收数据。比如:在IndexPage.js中通过connect接收model中保存的数据。

    /**
     * 使用@connect(),并且传递一个函数为参数时,代表接收model中保存的数据
     * 函数的参数state代表全局state,全局state保存了所有的model数据.
     * 函数的返回值会被保存到当前页面的props中,通过this.props.来获取
     */
    @connect((state) => ({demoData: state.demo.demoData}))
    export default class IndexPage extends React.Component {
    
      componentWillMount() {
        //打印接收的model数据
        console.log(this.props.demoData);
      }
    }  
    

    调试

    1 添加断点

    方法一:

    在代码中,添加代码debugger;,即在此处添加断点;

    方法二:

    在浏览器调试界面,选择Sources-top-webpack-internal://-.-src目录下,找到对应的js文件,然后在js页面左侧,左键点击提交断点。

    2 react-devtools调试

    react-devtools相比chrome的调试工具,功能更强大。通过在浏览器中安装这个插件,可以查看组件的层次、各个组件的Props、States等信息。

    下载地址:https://www.crx4chrome.com/down/62541/crx/

    安装步骤:先下载.crx文件,然后打开更多工具-扩展程序,然后将.crx文件拖进去

    3 Android调试

    首先,在android上安装Stetho:https://reactnative.cn/docs/debugging/

    然后,在谷歌浏览器上打开chrome://inspect

    注意:打开调试页面后,可以在地址输入栏打开自己的H5页面,这样就可以在自己的H5页面上调试Native的功能。

    常见问题

    1 npm查看模块版本

    查看服务器上的模块版本:

    1. 查看所有的版本信息:npm view [moduleName] versions
    2. 查看最新的版本信息:npm view [moduleName] version
    3. 查看完整的版本信息:npm info [moduleName]

    查看本地的模块版本:

    1. 查看本地安装的版本:npm ls [moduleName]。注意,需要在模块的安装目录执行命令,比如:package.json所在的目录。
    2. 查看全局安装的版本:npm ls [moduleName] -g

    2 npm安装模块

    2.1 指定版本安装模块:

    方法一:

    1. package.json的dependencies中声明模块名和版本号,比如:"redux": "^4.0.0"
    2. package.json所在的目录下,运行命令:npm install

    方法二:

    使用@[版本号],比如:npm i --save redux@4.0.0;

    2.2 自动安装合适版本的模块:

    package.json所在的目录下,运行命令:npm install --save [moduleName]

    如果要安装到开发环境,运行命令:npm install --save-dev [moduleName]

    2.3 ~和^的作用和区别:

    • 会匹配最新的小版本依赖包,比如1.2.3会匹配所有1.2.x版本,但是不包括1.3.0
    • 会匹配最新的大版本依赖包,比如1.2.3会匹配所有1.x.x的包,包括1.3.0,但是不包括2.0.0

    2.4 npm WARN处理

    安装模块时,可能因为缺少依赖组件导致部分组件安装失败,比如:

    npm WARN eslint-plugin-react-native@3.2.1 requires a peer of eslint@^3.17.0 || ^4.0.0 but none was installed.
    

    解决办法:

    安装缺少的依赖组件,比如:npm install --save eslint

    3 node-sass安装失败

    出现Cannot download https://github.com/sass/node-sass/releases/download/版本号/XXX_binding.nod情况,是因为node-sass被墙了。

    3.1 使用淘宝镜像源(推荐)

    设置变量 sass_binary_site,指向淘宝镜像地址。示例:

    npm i node-sass --sass_binary_site=https://npm.taobao.org/mirrors/node-sass/
    
    // 也可以设置系统环境变量的方式。示例
    // linux、mac 下
    SASS_BINARY_SITE=https://npm.taobao.org/mirrors/node-sass/ npm install node-sass
    
    // window 下
    set SASS_BINARY_SITE=https://npm.taobao.org/mirrors/node-sass/ && npm install node-sass
    

    或者设置全局镜像源:

    npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/
    

    3.2 使用cnpm安装

    npm install -g cnpm --registry=https://registry.npm.taobao.org
    
    cnpm i --save-dev node-sass
    

    最后

    代码:https://gitee.com/yanhuo2008/CommonH5

    相关文章

      网友评论

          本文标题:H5入门01-React+dva+webpack搭建项目框架

          本文链接:https://www.haomeiwen.com/subject/uewayqtx.html