next-video
Version:
A React component for adding video to your Next.js application. It extends both the video element and your Next app with features for automatic video optimization.
118 lines (117 loc) • 4.57 kB
JavaScript
import symlinkDir from "symlink-dir";
import { join, dirname } from "node:path";
import fs from "node:fs";
import { env } from "node:process";
import { fileURLToPath } from "node:url";
import logger from "./utils/logger.js";
import { getPackageVersion } from "./utils/utils.js";
import { setVideoConfig } from "./config.js";
let hasWarned = false;
function withNextVideo(nextConfig, videoConfig) {
const videoConfigComplete = setVideoConfig(videoConfig);
const { path, folder, provider } = videoConfigComplete;
env["NEXT_PUBLIC_VIDEO_OPTS"] = JSON.stringify({ path, folder, provider });
if (process.argv[2] === "dev") {
env["NEXT_PUBLIC_DEV_VIDEO_OPTS"] = JSON.stringify({ path, folder, provider });
}
if (typeof nextConfig === "function") {
return async (...args) => {
const nextConfigResult = await nextConfig(...args);
return withNextVideo(nextConfigResult, videoConfig);
};
}
if (process.argv[2] === "dev") {
const VIDEOS_PATH = join(process.cwd(), folder);
const TMP_PUBLIC_VIDEOS_PATH = join(process.cwd(), "public", `_next-video`);
symlinkDir(VIDEOS_PATH, TMP_PUBLIC_VIDEOS_PATH);
process.on("exit", async () => {
fs.unlinkSync(TMP_PUBLIC_VIDEOS_PATH);
});
}
const nextVersion = getPackageVersion("next");
if (nextVersion && nextVersion.startsWith("15.")) {
nextConfig.outputFileTracingIncludes = {
...nextConfig.outputFileTracingIncludes,
[path]: [`./${folder}/**/*.json`]
};
} else {
const experimental = { ...nextConfig.experimental };
experimental.outputFileTracingIncludes = {
...experimental.outputFileTracingIncludes,
[path]: [`./${folder}/**/*.json`]
};
nextConfig.experimental = experimental;
}
if (!hasWarned && process.env.TURBOPACK && !process.env.NEXT_VIDEO_SUPPRESS_TURBOPACK_WARNING) {
hasWarned = true;
const nextVideoVersion = getPackageVersion("next-video");
logger.space(logger.label(`\u25B6\uFE0E next-video ${nextVideoVersion}
`));
logger.warning(
`You are using next-video with \`next ${true ? "dev" : "build"} --turbo\`. next-video doesn't yet fully support Turbopack.
We recommend temporarily removing the \`--turbo\` flag for use with next-video.
`
);
logger.warning(
`Follow this issue for progress on next-video + Turbopack: https://github.com/muxinc/next-video/issues/266.
(You can suppress this warning by setting NEXT_VIDEO_SUPPRESS_TURBOPACK_WARNING=1 as environment variable)
`
);
}
return Object.assign({}, nextConfig, {
webpack(config, options) {
if (!options.defaultLoaders) {
throw new Error(
"This plugin is not compatible with Next.js versions below 5.0.0 https://err.sh/next-plugins/upgrade"
);
}
config.infrastructureLogging = {
...config.infrastructureLogging,
// Silence warning about dynamic import of next.config file.
// > [webpack.cache.PackFileCacheStrategy/webpack.FileSystemInfo] Parsing of /next-video/dist/config.js for build dependencies failed at 'import(fileUrl.
// > Build dependencies behind this expression are ignored and might cause incorrect cache invalidation.
level: "error"
};
config.experiments.buildHttp = {
allowedUris: [
/https?:\/\/.*\.(mp4|webm|mkv|ogg|ogv|wmv|avi|mov|flv|m4v|3gp)\??(?:&?[^=&]*=[^=&]*)*$/,
...config.experiments.buildHttp?.allowedUris ?? []
],
...config.experiments.buildHttp || {},
// Disable cache to prevent Webpack from downloading the remote sources.
cacheLocation: false
};
const scriptDir = typeof __dirname === "string" ? __dirname : dirname(fileURLToPath(import.meta.url));
config.module.rules.push(
{
test: /\.(mp4|webm|mkv|ogg|ogv|wmv|avi|mov|flv|m4v|3gp)\??(?:&?[^=&]*=[^=&]*)*$/,
use: [
{
loader: join(scriptDir, "webpack/video-json-loader.js")
},
{
loader: join(scriptDir, "webpack/video-raw-loader.js")
}
],
type: "json"
},
{
test: /\.(mp4|webm|mkv|ogg|ogv|wmv|avi|mov|flv|m4v|3gp)\.json\??(?:&?[^=&]*=[^=&]*)*$/,
use: [
{
loader: join(scriptDir, "webpack/video-json-loader.js")
}
],
type: "json"
}
);
if (typeof nextConfig.webpack === "function") {
return nextConfig.webpack(config, options);
}
return config;
}
});
}
export {
withNextVideo
};