React native 已有项目升级兼容web

基础

概念 | webpack 中文文档 | webpack 中文文档 | webpack 中文网

深入理解Webpack及Babel的使用 - 掘金

Introduction to React Native for Web // React Native for Web

Webpack 是一个现代的 JavaScript 应用程序的静态模块打包工具,它将应用程序所依赖的各种资源(js、css、图片等)视为模块,通过 loader 转换这些模块,最后打包成符合生产环境部署的静态资源。

Webpack 的运行机制基于一条简单的原则:一切文件皆模块。因此,Webpack 在构建应用程序时,会先从入口模块开始递归解析模块依赖,然后通过 loader 处理各种类型的模块,最后打包成一个或多个浏览器可识别的静态资源。

Webpack 的基本配置包括 entry、output、module 和 plugins 四个部分。其中,entry 指定了入口模块,output 指定了输出目录和输出文件名,module 则用于配置 loader 和其他的一些规则,plugins 则是用于扩展 Webpack 功能的插件。

在使用 Webpack 进行项目开发时,我们通常需要使用 Babel 将 ES6+ 代码转换成浏览器兼容的 ES5 代码。Babel 的作用是将 JavaScript 新特性转换成浏览器支持的语法,例如箭头函数、解构赋值等。而 Loader 则是 Webpack 中用于处理各种类型文件的工具,例如将 css 转换成 JavaScript 对象、将图片转换成 data URL 等。

Babel是一个JavaScript编译器,可以将最新版本的JavaScript转换为向后兼容的代码,以便在旧版浏览器或其他环境中运行。Babel的作用是让我们使用最新的JavaScript语法特性,而不必担心浏览器是否支持这些特性。

过程

yarn add react-dom react-native-web
yarn add react-native-reanimated
yarn add -D babel-plugin-react-native-web
yarn add -D babel-loader url-loader webpack webpack-cli webpack-dev-server
yarn add -D babel-plugin-react-native-web
#每次打包发布时自动清理掉 dist 目录中的旧文件,
yarn add -D clean-webpack-plugin


#html-webpack-plugin的主要作用就是在webpack构建后生成html文件,同时把构建好入口js文件引入到生成的html文件中。
yarn add -D html-webpack-plugin

webpack.config.js

const path = require('path');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');

const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const appDirectory = path.resolve(__dirname);
// const {presets} = require(`${appDirectory}/babel.config.js`);

const compileNodeModules = [
  // Add every react-native package that needs compiling
  // 'react-native-gesture-handler',
].map((moduleName) => path.resolve(appDirectory, `node_modules/${moduleName}`));

const baseProjectSource = [
  path.resolve(appDirectory, 'web/index.web.js'), // Entry to your application
  path.resolve(appDirectory, 'web/App.web.js'), // Change this to your main App file
  path.resolve(appDirectory, './src'),
];


const babelLoaderConfiguration = {
  test: /\.(js|jsx|ts|tsx)$/,
  // Add every directory that needs to be compiled by Babel during the build.
  include: baseProjectSource,
  use: {
    loader: 'babel-loader',
    options: {
      cacheDirectory: true,
      // The 'react-native' preset is recommended to match React Native's packager
      presets: ['module:metro-react-native-babel-preset'],
      // Re-write paths to import only the modules needed by the app
      plugins: ['react-native-web', 'react-native-reanimated/plugin'],
    },
  },
};


const imageLoaderConfiguration = {
  test: /\.(gif|jpe?g|png)$/,
  use: {
    loader: 'url-loader',
    options: {
      name: '[name].[ext]',
    },
  },
};

module.exports = {
  entry: {
    app: path.join(appDirectory, 'web/index.web.js'),
  },
  output: {
    path: path.resolve(appDirectory, 'dist'),
    publicPath: '/',
    filename: 'upup.bundle.js',
  },
  resolve: {
    // If you're working on a multi-platform React Native app, web-specific
    // module implementations should be written in files using the extension
    // `.web.js`.
    extensions: ['.web.tsx', '.web.ts', '.tsx', '.ts', '.web.js', '.js'],
    alias: {
      'react-native$': 'react-native-web',
    },
  },
  module: {
    rules: [
      babelLoaderConfiguration,
      imageLoaderConfiguration,
    ],
  },
  devServer: {
    port: 8080,
    historyApiFallback: true,
    open: !process.env.CI,
  }, 
  plugins: [
    new CleanWebpackPlugin({
      cleanOnceBeforeBuildPatterns: [
        '**/*'
      ]
    }),
    // `process.env.NODE_ENV === 'production'` must be `true` for production
    // builds to eliminate development checks and reduce build size. You may
    // wish to include additional optimizations.
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
      __DEV__: process.env.NODE_ENV === 'production' || true
    }),
    new HtmlWebpackPlugin({
      template: path.join(appDirectory, 'web/index.html'),
    }),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.DefinePlugin({
      // See: https://github.com/necolas/react-native-web/issues/349
      __DEV__: JSON.stringify(true),
    }),
  ],
};

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>RN Web</title>
    <style>
      #app-root {
        display: flex;
        flex: 1 1 100%;
        height: 100vh;
      }
    </style>
  </head>
  <body>
    <div id="app-root"></div>
  </body>
</html>

index.web.js

import {AppRegistry} from 'react-native';
import appInfo from '../app.json';
import App from './App.web';


AppRegistry.registerComponent(appInfo.name, () => App);
AppRegistry.runApplication(appInfo.name, {
  initialProps: {},
  rootTag: document.getElementById('app-root'),
});

App.web.js

import React from 'react';
import FaqTestnet from '../src/screen/FaqTestnet';
import AboutTestnet from '../src/screen/AboutTestnet';
import 'react-native-gesture-handler';
import {NavigationContainer} from '@react-navigation/native';
import {
  createStackNavigator,
  CardStyleInterpolators,
} from '@react-navigation/stack';
import Color from "../src/app/Color";
import DarkTheme from '../src/app/DarkTheme';

const Stack = createStackNavigator();

const config = {
  screens: {
    FaqTestnet: 'faqtestnet',
    AboutTestnet: 'abouttestnet',
  },
};

const linking = {
  prefixes: ['http://tokshow.io',  'http://localhost:8080', 'http://127.0.0.1:5500/'],
  config,
};

function App() {
  return (
    <NavigationContainer linking={linking} fallback={<Text>Loading...</Text>} theme={DarkTheme}>
      <Stack.Navigator
        initialRouteName="AboutTestnet"
        screenOptions={{
          animationEnabled: false,
          headerShown: false,
          unmountOnBlur: false,
          cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS,
        }}>
        <Stack.Screen
          name="FaqTestnet"
          component={FaqTestnet}
          options={{
            title: 'Testnet FAQ',
          }}
        />
        <Stack.Screen
          name="AboutTestnet"
          component={AboutTestnet}
          options={{
            title: 'About the Incentivized Testnet',
          }}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

export default App;

package.json

  "scripts": {
    "web:release": "export NODE_ENV=production && rm -rf dist/ && webpack --config ./webpack.config.js",
    "web": "export NODE_ENV=development && webpack-dev-server --config ./webpack.config.js",

参考

How to Make Your React Native Apps Work on the Web

相关推荐
光影少年18 分钟前
vue2与vue3的全局通信插件,如何实现自定义的插件
前端·javascript·vue.js
Rattenking23 分钟前
React 源码学习01 ---- React.Children.map 的实现与应用
javascript·学习·react.js
熊的猫1 小时前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js
别拿曾经看以后~3 小时前
【el-form】记一例好用的el-input输入框回车调接口和el-button按钮防重点击
javascript·vue.js·elementui
川石课堂软件测试3 小时前
性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台
运维·javascript·深度学习·jmeter·docker·容器·grafana
JerryXZR3 小时前
前端开发中ES6的技术细节二
前端·javascript·es6
problc4 小时前
Flutter中文字体设置指南:打造个性化的应用体验
android·javascript·flutter
Gavin_9154 小时前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼5 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
小牛itbull6 小时前
ReactPress:重塑内容管理的未来
react.js·github·reactpress