diff --git a/example/index.web.js b/example/index.web.js
new file mode 100644
index 00000000..f4124016
--- /dev/null
+++ b/example/index.web.js
@@ -0,0 +1,8 @@
+import { AppRegistry } from 'react-native';
+import { name as appName } from './app.json';
+import App from './src/App';
+
+AppRegistry.registerComponent(appName, () => App);
+AppRegistry.runApplication(appName, {
+ rootTag: document.getElementById('root'),
+});
diff --git a/example/package.json b/example/package.json
index 4e12fd24..3fa135dc 100644
--- a/example/package.json
+++ b/example/package.json
@@ -9,12 +9,16 @@
"typecheck": "tsc",
"start": "react-native start --client-logs",
"bundle-install": "bundle install",
- "pods": "cd ios && pod install && cd .."
+ "pods": "cd ios && pod install && cd ..",
+ "web": "webpack serve --mode development --config web/webpack.config.js",
+ "build:web": "webpack --mode production --config web/webpack.config.js"
},
"dependencies": {
"@react-native-community/slider": "^4.5.6",
"react": "18.3.1",
+ "react-dom": "18.3.1",
"react-native": "^0.77.0",
+ "react-native-web": "^0.19.13",
"react-native-nitro-modules": "0.35.0",
"react-native-video": "*",
"@react-native-video/drm": "*"
@@ -33,7 +37,16 @@
"@types/react": "^18.2.44",
"eslint": "^8.51.0",
"prettier": "^3.0.3",
- "typescript": "^5.2.2"
+ "typescript": "^5.2.2",
+ "webpack": "^5.97.0",
+ "webpack-cli": "^6.0.0",
+ "webpack-dev-server": "^5.2.0",
+ "babel-loader": "^9.2.1",
+ "babel-plugin-react-native-web": "^0.19.13",
+ "url-loader": "^4.1.1",
+ "html-webpack-plugin": "^5.6.3",
+ "style-loader": "^4.0.0",
+ "css-loader": "^7.1.2"
},
"engines": {
"node": ">=18"
diff --git a/example/web/index.html b/example/web/index.html
new file mode 100644
index 00000000..ec654c90
--- /dev/null
+++ b/example/web/index.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+ React Native Video - Example
+
+
+
+
+
+
diff --git a/example/web/webpack.config.js b/example/web/webpack.config.js
new file mode 100644
index 00000000..d56a155c
--- /dev/null
+++ b/example/web/webpack.config.js
@@ -0,0 +1,85 @@
+const path = require('path');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+
+const appDirectory = path.resolve(__dirname, '../');
+const rootDirectory = path.resolve(__dirname, '../../');
+
+const babelLoaderConfiguration = {
+ test: /\.(js|jsx|ts|tsx)$/,
+ include: [
+ path.resolve(appDirectory, 'index.web.js'),
+ path.resolve(appDirectory, 'src'),
+ // Monorepo packages that need transpiling
+ path.resolve(rootDirectory, 'packages/react-native-video/src'),
+ ],
+ use: {
+ loader: 'babel-loader',
+ options: {
+ cacheDirectory: true,
+ presets: [
+ '@babel/preset-env',
+ ['@babel/preset-react', { runtime: 'automatic' }],
+ '@babel/preset-typescript',
+ ],
+ plugins: ['react-native-web'],
+ },
+ },
+};
+
+const imageLoaderConfiguration = {
+ test: /\.(gif|jpe?g|png|svg)$/,
+ use: {
+ loader: 'url-loader',
+ options: { name: '[name].[ext]' },
+ },
+};
+
+const cssLoaderConfiguration = {
+ test: /\.css$/,
+ use: ['style-loader', 'css-loader'],
+};
+
+module.exports = {
+ entry: path.resolve(appDirectory, 'index.web.js'),
+ output: {
+ filename: 'bundle.web.js',
+ path: path.resolve(appDirectory, 'dist'),
+ },
+ module: {
+ rules: [
+ babelLoaderConfiguration,
+ imageLoaderConfiguration,
+ cssLoaderConfiguration,
+ ],
+ },
+ resolve: {
+ alias: {
+ 'react-native$': 'react-native-web',
+ // Native-only modules that should not be bundled on web
+ 'react-native-nitro-modules': false,
+ '@react-native-video/drm': false,
+ // Resolve react-native-video from source (not lib/) for web
+ 'react-native-video': path.resolve(rootDirectory, 'packages/react-native-video/src'),
+ },
+ extensions: [
+ '.web.tsx', '.web.ts', '.web.js',
+ '.tsx', '.ts', '.js', '.jsx', '.json',
+ ],
+ // Monorepo: resolve packages from both example and root node_modules
+ modules: [
+ path.resolve(appDirectory, 'node_modules'),
+ path.resolve(rootDirectory, 'node_modules'),
+ 'node_modules',
+ ],
+ },
+ plugins: [
+ new HtmlWebpackPlugin({
+ template: path.resolve(appDirectory, 'web/index.html'),
+ }),
+ ],
+ devServer: {
+ static: path.resolve(appDirectory, 'dist'),
+ hot: true,
+ port: 8080,
+ },
+};
diff --git a/packages/react-native-video/src/core/video-view/VideoView.web.tsx b/packages/react-native-video/src/core/video-view/VideoView.web.tsx
index 9fb5a020..26544c25 100644
--- a/packages/react-native-video/src/core/video-view/VideoView.web.tsx
+++ b/packages/react-native-video/src/core/video-view/VideoView.web.tsx
@@ -13,6 +13,7 @@ import type { ListenerSubscription } from "../types/EventEmitter";
import type { VideoViewProps, VideoViewRef } from "./VideoViewProps";
import { createPlayer, videoFeatures, usePlayerContext, useMediaAttach } from "@videojs/react";
import { VideoSkin } from "@videojs/react/video";
+import "@videojs/react/video/skin.css";
const Player = createPlayer({ features: videoFeatures });