Angular13升级至15后,webpack_require.context不是函数报错如何解决?
问题:Angular13迁移至Angular15后
require.context调用报错 我开发了一个文档应用,支持在组件示例旁查看TS、HTML、SCSS源码及运行效果。从Angular13迁移到Angular15后出现如下问题:
在AppModule的providers中配置了令牌:
{ provide: DEMO_PATH_TOKEN_SCSS, useFactory: () => (require as any).context(`!sass-loader!./`, true, /.*\.(scss)$/), }
这个工厂函数用于获取源码文件列表,后续由承载示例的容器组件过滤;TS和HTML文件也有类似配置。
该令牌注入到非根级提供的SourcesService中:
@Injectable() export class SourcesService { constructor( @SkipSelf() @Optional() @Inject(DEMO_PATH_TOKEN_SCSS) private contextScss: any ) { } }
打开提供SourcesService的组件页面时,触发错误:
ERROR Error: Uncaught (in promise): TypeError: webpack_require(...).context is not a function
TypeError: webpack_require(...).context is not a function
修复方案
1. 适配Webpack 5的require.context写法
Angular15升级至Webpack 5,require.context不支持运行时动态调用,需提前创建上下文并导出:
在项目根目录创建demo-contexts.ts文件:
// 提前创建SCSS文件上下文 export const scssDemoContext = require.context(`!sass-loader!./`, true, /.*\.(scss)$/); // 同理创建TS和HTML的上下文 export const tsDemoContext = require.context(`!raw-loader!./`, true, /.*\.(ts)$/); export const htmlDemoContext = require.context(`!raw-loader!./`, true, /.*\.(html)$/);
修改AppModule的providers配置,直接引用导出的上下文:
import { scssDemoContext, tsDemoContext, htmlDemoContext } from './demo-contexts'; @NgModule({ providers: [ { provide: DEMO_PATH_TOKEN_SCSS, useValue: scssDemoContext }, // TS和HTML的令牌配置同理 { provide: DEMO_PATH_TOKEN_TS, useValue: tsDemoContext }, { provide: DEMO_PATH_TOKEN_HTML, useValue: htmlDemoContext } ] }) export class AppModule { }
2. 确保loader配置正确
Angular15默认配置有变化,需确保raw-loader和sass-loader已安装并配置:
安装依赖:
npm install raw-loader sass-loader --save-dev
在angular.json的build配置中添加允许的CommonJS依赖:
"build": { "builder": "@angular-devkit/build-angular:browser", "options": { "allowedCommonJsDependencies": ["sass-loader"], "stylePreprocessorOptions": { "includePaths": ["./src"] } } }
若需自定义Webpack规则,创建webpack.config.js:
module.exports = { module: { rules: [ { test: /\.scss$/, use: ['raw-loader', 'sass-loader'], exclude: /node_modules/ }, { test: /\.ts$/, use: ['raw-loader'], exclude: /node_modules/ }, { test: /\.html$/, use: ['raw-loader'], exclude: /node_modules/ } ] } };
3. 调整SourcesService注入逻辑
确保依赖注入规则符合Angular规范,避免令牌重复提供冲突:
@Injectable({ providedIn: 'any' // 或根据实际场景设置为对应特性模块 }) export class SourcesService { constructor( @Optional() @Inject(DEMO_PATH_TOKEN_SCSS) private contextScss: any ) { // 添加空值判断,避免无上下文时报错 if (!this.contextScss) { console.warn('SCSS demo context not provided'); } } }
内容的提问来源于stack exchange,提问作者Eugeny89
相关产品推荐
相关产品推荐

