浏览器场景导入node modules问题及Webpack打包困惑
问题解决指南
一、直接引用node_modules的问题根源与临时修复
你遇到的导入.d.ts文件、扩展名报错问题,本质是浏览器原生ES模块不支持直接解析npm包的导入逻辑,且VSCode的自动导入误识别了类型文件:
.d.ts是TypeScript类型声明文件,仅用于代码提示,不能在浏览器中运行- 浏览器原生ES模块要求导入必须带完整扩展名(
.js/.mjs),但npm包的入口通常定义在package.json的main或module字段,原生模块无法识别这个逻辑
临时修复(不使用Webpack时)
- 不要直接导入
node_modules下的具体文件,而是导入包名(需配合es-module-shims这类工具让服务器支持模块解析) - 修改
jsconfig.json,配置paths让VSCode正确识别包的入口:
{ "compilerOptions": { "module": "ESNext", "baseUrl": "./", "paths": { "@eonasdan/tempus-dominus": ["node_modules/@eonasdan/tempus-dominus/dist/js/tempus-dominus.js"] } }, "include": ["**/*.js"] }
配置后VSCode自动导入时会指向正确的JS文件,而非类型文件。
二、Webpack适配「PHP页面对应独立JS」的打包方案
你的场景适合多入口打包+公共依赖拆分:把所有页面JS作为独立入口,同时把dependencies.js里的公共依赖抽成单独的vendor包,避免每个页面重复打包依赖。
1. 修改Webpack配置文件
更新webpack.config.js,支持多入口、公共依赖拆分,同时保留样式打包(需先安装glob:yarn add glob -D):
const path = require("path"); const glob = require("glob"); // 获取所有页面JS文件(假设页面JS都在cp/pages目录下,比如Home.js、About.js) const entryPoints = glob.sync("./cp/pages/*.js").reduce((acc, filePath) => { const fileName = path.basename(filePath, ".js"); acc[fileName] = filePath; return acc; }, { // 保留公共依赖入口 dependencies: "./cp/dependencies.js" }); module.exports = { mode: "development", entry: entryPoints, output: { filename: "[name].bundle.js", path: path.resolve(__dirname, "cp", "dist"), clean: true // 每次打包清空dist目录 }, optimization: { splitChunks: { chunks: "all", // 把公共依赖抽成vendor.bundle.js cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name: "vendor", chunks: "all" } } } }, module: { rules: [ { test: /\.css$/i, use: ["style-loader", "css-loader"], }, ], }, };
2. 页面JS的写法调整
每个页面JS(比如Home.js)可以直接导入npm包,无需写冗长的相对路径,Webpack会自动解析:
// Home.js import { TempusDominus } from "@eonasdan/tempus-dominus"; document.addEventListener('DOMContentLoaded', () => { const tmp = new TempusDominus(document.getElementById('datetimepicker')); });
3. PHP页面引入打包后的文件
在对应的PHP页面(比如Home.php)中,按顺序引入公共依赖与页面专属JS:
<!-- Home.php --> <script src="/cp/dist/vendor.bundle.js"></script> <script src="/cp/dist/dependencies.bundle.js"></script> <script src="/cp/dist/Home.bundle.js"></script>
三、关于全局挂载与模块的选择
如果不想用ES模块写法,希望继续用全局变量(比如$、TempusDominus),可以修改dependencies.js的导入方式,确保全局变量挂载:
// dependencies.js // 导入jQuery并挂载到window import $ from 'jquery'; window.$ = window.jQuery = $; // Bootstrap等依赖会自动识别全局的$,无需额外处理 import 'bootstrap/dist/js/bootstrap.bundle'; // 其他包同理 import '@eonasdan/tempus-dominus/dist/js/tempus-dominus';
打包后页面JS可以直接使用全局变量,无需写导入语句。
内容的提问来源于stack exchange,提问作者zainsyedz
相关产品推荐
相关产品推荐

