当前位置: 首页 > 知识库问答 >
问题:

通过`webpack`打包为esm包,`npm link`后包空对象,请问是怎么回事?

卢聪
2023-12-26

请问通过webpack打包为esm包,npm link后包空对象,请问是怎么回事?导出的包有编译,npm link后得到的是{}对象

两个文件metab.ts

const metab = {aa: 1};export default metab;

入口文件metas.ts引入metab.ts

import metab from "./metab";const metas = metab;export default metas;

这样打包后npm link,在其他项目里导入metas.ts,得到是一个空对象{},如果我把metas.ts去掉import,直接写上值可以得到结果

const metas = {aa: 1};export default metas;

请问不能import是怎么回事呢?我的webpack配置

const HtmlWebpackPlugin = require('html-webpack-plugin');const path = require('path');// 根据环境变量,判断当前是否为生产模式。const isProduction = process.env.NODE_ENV === 'production';// 读取当前的输出格式(UMD/ESM)const outputType = process.env.OUTPUT_TYPE;/** @type {import('webpack').Configuration} */const config = {    // 打包输出 ESM 格式文件,最终要输出多个文件,便于实现按需加载,因此设置为多入口    entry: outputType === 'esm' ? {        metas: './src/calc/metas.ts'    } : (        isProduction ? './src/calc/index.ts' : './src/index.ts'    ),    // 由于输出 ESM 格式文件为 Webpack 实验特性,因此需要加上此配置。    experiments: {        outputModule: outputType === 'esm'    },    // 根据环境变量决定    mode: isProduction ? 'production' : 'development',    // Babel与TS配置    module: {        rules: [            {                exclude: /node_modules/,                test: /\.ts(x?)$/,                use: [                    {                        loader: 'babel-loader',                        options: {                            presets: [['@babel/preset-env']]                        }                    },                    { loader: 'ts-loader' }                ]            }        ]    },    // 针对不同的环境变量,执行不同的打包动作。    output: outputType === 'esm' ? {        chunkFormat: 'module',        clean: true,        filename: '[name].esm.js',        library: {            type: 'module'        },        path: path.resolve(__dirname, 'es')    } : {        clean: true,        filename: 'index.js',        globalObject: 'globalThis',  // 设置全局对象为 globalThis,使库同时兼容 Node.js 与浏览器环境。        library: {            export: 'default',  // 指定将入口文件的默认导出作为库暴露。            name: 'calc',       // 指定库名称            type: 'umd'         // 输出的模块化格式, umd 表示允许模块通过 CommonJS、AMD 或作为全局变量使用。        },        path: path.resolve(__dirname, 'lib')    },    plugins: [        // 引入 html-webpack-plugin,只需在开发环境时使用。        ...(!isProduction ? [new HtmlWebpackPlugin()] : [])    ],    // 使路径查找时,支持省略文件名的ts后缀    resolve: {        extensions: ['.js', '.json', '.jsx', '.ts', '.tsx']    }};module.exports = config;

共有2个答案

慎星纬
2023-12-26

找到解决办法了,esm,导出的方式为export {} https://zhuanlan.zhihu.com/p/40733281

卫才
2023-12-26

看起来,你正在使用 webpack 来打包你的 JavaScript 代码,并试图将结果通过 npm link 在其他项目中引入。问题在于,你引入的模块是一个 ESM 模块,而不是一个 UMD 模块。

Webpack 默认打包的 ESM 模块(使用 output.library 和 output.chunkFormat: 'module')在浏览器环境中可能无法直接使用,因为浏览器可能不支持 ES 模块。而 npm link 是在浏览器环境中运行的,所以它可能无法正确解析你的 ESM 模块。

解决这个问题的一种方式是,你可以尝试将你的 webpack 配置改为打包 UMD 模块,而不是 ESM 模块。你可以通过修改 output.library 和 output.chunkFormat 的值来实现这个目标。

以下是你的 webpack 配置,我将它修改为打包 UMD 模块:

const HtmlWebpackPlugin = require('html-webpack-plugin');const path = require('path');// 根据环境变量,判断当前是否为生产模式。const isProduction = process.env.NODE_ENV === 'production';// 读取当前的输出格式(UMD/ESM)const outputType = process.env.OUTPUT_TYPE;/** @type {import('webpack').Configuration} */const config = {    // 打包输出 UMD 格式文件,最终要输出多个文件,便于实现按需加载,因此设置为多入口    entry: outputType === 'esm' ? {        metas: './src/calc/metas.ts'    } : (        isProduction ? './src/calc/index.ts' : './src/index.ts'    ),    // 由于输出 UMD 格式文件为 Webpack 实验特性,因此需要加上此配置。    experiments: {        outputModule: outputType === 'esm'    },    // 根据环境变量决定    mode: isProduction ? 'production' : 'development',    // Babel与TS配置    module: {        rules: [            {                exclude: /node_modules/,                test: /\.ts(x?)$/,                use: [                    {                        loader: 'babel-loader',                        options: {                            presets: [['@babel/preset-env']]                        }                    },                    { loader: 'ts-loader' }                ]            }        ]    },    // 针对不同的环境变量,执行不同的打包动作。    output: outputType === 'esm' ? {        chunkFormat: 'module',        clean: true,        filename: '[name].esm.js',        library: {            type: 'module'        },        path: path.resolve(__dirname, 'es')    } : {        clean: true,        filename: 'index.js',        globalObject: 'globalThis',  // 设置全局对象为 globalThis,使库同时兼容 Node.js 与浏览器环境。        library: {            export: 'default',  // 指定将入口文件的默认导出作为库暴露。            name: 'calc',       // 指定库名称            type: 'umd'         // 这里需要改为 'umd',而不是 'module'。输出的模块化格式, umd 表示允许模块通过 CommonJS、AMD 或作为全局变量使用。        },        path: path.resolve(__dirname, 'lib')    },    plugins: [        // 引入 html-webpack-plugin,只需在开发环境时使用。        ...(!isProduction ? [new HtmlWebpackPlugin()] : [])    ],    // 使路径查找时,支持省略文件名的ts后缀    resolve: {        extensions: ['.js', '.json', '.jsx', '.ts', '.tsx']    }};module.exports = config;

请注意,我修改了 output.library 的 type 值从 'module' 改为 'umd'。这应该解决你的问题。如果问题仍然存在,请尝试清除你的 node_modules 文件夹和 package-lock.json 文件,然后重新运行 npm install。

 类似资料:
  • 本文向大家介绍webpack打包文件太大怎么办?相关面试题,主要包含被问及webpack打包文件太大怎么办?时的应答技巧和注意事项,需要的朋友参考一下 webpack把我们所有的文件都打包成一个JS文件,这样即使你是小项目,打包后的文件也 会非常大。可以从去除不必要的插件,提取第三方库,代码压缩,代码分割,设置缓存几个 方面着手优化。 详细参见:http://www.jianshu.com/p/a

  • 请教Webpack打包后找不到资源? 入口文件如下: 打包在lib目录,如下: 入口文件index_bundle.js在package.json中设置main指向./lib/index_bundle.js就好了 但是874.index_bundle.js这个文件就找不到了,提示如下 于是我去查了下,说是要设置homepage 但是无论我是设置./lib/还是设置.,都不对 于是我想是不是要将hom

  • 本文向大家介绍webpack打包vue速度太慢怎么办?相关面试题,主要包含被问及webpack打包vue速度太慢怎么办?时的应答技巧和注意事项,需要的朋友参考一下 https://www.cnblogs.com/imwtr/p/9189670.html

  • vue3+vite打包的时候,报错Access is denied,请问怎么解决啊?重新装了node_modules包,用nvm试了npm的几个版本都不行

  • "webpack-obfuscator": "2.6.0" 更新到生产环境发现有一个页面打不开,我排除掉node_modules,但是好像不生效,不知道什么原因。 有问题的页面用到了tinymce和moment 怎么解决?

  • 通过vite中rollup打包,如何对lodash做按需打包? 这两种写法在build时 第一种dist体积比第二种要大。都说是第一种写法是将整个lodash打包进了dist。我这里有一个疑问,rollup在build时不是会对代码做按需打包吗? rollup的树摇不会起作用吗? 假设整个项目只使用了一个throttle函数,也会将整个lodash打包到dist吗? 虽然lodash是 cjs规范