Forum Discussion
SPFX 1.21.1 in monorepo - utility module could not be exported
I am trying to migrate multiple projects to monorepo. I need to migrate some common utilities functions in a common module.
There is an export warning that the module has no exports, while it does has.
Running npm run spfx1:build works fine. But when I do npm run spfx1:serve it throws a warning
export 'DemoUtilities' (imported as 'DemoUtilities') was not found in 'utilities-library/utils' (module has no exports)Opening the a SharePoint page online, it errors with missing exports.
Can you point me to possible solutions?
Here is a very simple OOB SPFX solution structure:
utilities-library
- src
-- utils.ts
- index.ts
- package.json
- tsconfig.json
spfx1
- config
- sharepoint
- src
-- skipped for brevity
- gulpfile.js
- package.json
- tsconfig.json
package.json
tsconfig.base.json
Specifics for per files
utilities-library -> package.json
{
"name": "utilities-library",
"version": "1.0.0",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"scripts": {
"start": "node index.js",
"test": "echo \"test\""
},
"type": "module",
"workspaces": [
"true"
],
"devDependencies": {
"typescript": "^5.3.5"
}
}utilities-library ->tsconfig.json
{
"compilerOptions": {
"composite": true,
"declaration": true,
"outDir": "lib"
},
"include": ["**/*.ts"]
}utilities-library ->index.ts
export { DemoUtilites } from './src/utils';utilities-library -> utils.ts
import { ISPFXContext, spfi, SPFx } from "@pnp/sp";
import "@pnp/sp/webs";
import "@pnp/sp/lists";
export const DemoUtilites = {
checkListExists: async (
listTitle: string,
context: ISPFXContext
): Promise<boolean> => {
const sp = spfi().using(SPFx(context));
return new Promise<boolean>((resolve) => {
sp.web.lists
.getByTitle(listTitle)()
.then(() => {
resolve(true);
})
.catch((error) => {
if (!(error?.status === 404)) {
console.log(`Error checking list ${listTitle}`, error);
}
resolve(false);
});
});
}
}spfx1 -> gulpfile.js
'use strict';
const build = require('@microsoft/sp-build-web');
const path = require("path");
build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);
build.configureWebpack.mergeConfig({
additionalConfiguration: (generatedConfig) => {
generatedConfig.resolve = generatedConfig.resolve || {};
generatedConfig.resolve.alias = {
...(generatedConfig.resolve.alias || {}),
'utilities-library': path.resolve(__dirname, '../utilities-library/lib'),
'utilities-library/utils': path.resolve(__dirname, '../utilities-library/lib/utils')
};
return generatedConfig;
}
});
var getTasks = build.rig.getTasks;
build.rig.getTasks = function () {
var result = getTasks.call(build.rig);
result.set('serve', result.get('serve-deprecated'));
return result;
};
build.initialize(require('gulp'));spfx1 -> package.json
{
...
"dependencies": {
"@microsoft/decorators": "1.21.1",
"@microsoft/sp-core-library": "1.21.1",
"@microsoft/sp-dialog": "1.21.1",
"@microsoft/sp-listview-extensibility": "1.21.1",
"@pnp/sp": "^4.12.0",
"utilities-library": "^1.0.0",
"office-ui-fabric-react": "^7.204.1",
"react": "17.0.1",
"react-dom": "17.0.1",
"tslib": "2.3.1"
},
...
}spfx1 -> tsconfig.json
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "lib"
},
"include": ["src/**/*.ts", "src/**/*.tsx"],
"references": [
{ "path": "../utilities-library" }
]
}root -> package.json
{
"name": "monorepo-test",
"workspaces": [
"spfx1",
"utilities-library"
],
"scripts": {
"spfx1:build": "gulp build -f ./spfx1/gulpfile.js --workspace spfx1",
"spfx1:clean": "gulp clean -f ./spfx1/gulpfile.js --workspace spfx1",
"spfx1:serve": "gulp serve -f ./spfx1/gulpfile.js --workspace spfx1 --nobrowser",
"spfx1:bundle": "gulp bundle -f ./spfx1/gulpfile.js --workspace spfx1",
"spfx1:pkg": "gulp package-solution -f ./spfx1/gulpfile.js --workspace spfx1",
"spfx1:prod": "gulp build -f ./spfx1/gulpfile.js --workspace spfx1 --ship & gulp bundle -f ./spfx1/gulpfile.js --workspace spfx1 --ship & gulp package-solution -f ./spfx1/gulpfile.js --workspace spfx1 --ship",
"utilities-library:build": "tsc --project utilities-library/tsconfig.json",
"utilities-library:watch": "npm run utilities-library:build -- --watch",
"clean:node": "rm -rf **/node_modules"
},
"devDependencies": {
"npm-run-all": "^4.1.5"
}
}root -> tsconfig.base.json
{
"extends": "./node_modules/@microsoft/rush-stack-compiler-5.3/includes/tsconfig-web.json",
"compilerOptions": {
"target": "es5",
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"jsx": "react",
"declaration": true,
"sourceMap": true,
"experimentalDecorators": true,
"skipLibCheck": true,
"outDir": "lib",
"inlineSources": false,
"noImplicitAny": true,
"rootDir": ".",
"baseUrl": ".", // Important for path mapping
"paths": {
"utilities-library/*": [
"utilities-library/lib/*"
]
},
"typeRoots": [
"./node_modules/@types",
"./node_modules/@microsoft"
],
"types": [
"webpack-env"
],
"lib": [
"es5",
"dom",
"es2015.collection",
"es2015.promise"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx"
]
}
2 Replies
- Kiril IlievCopper Contributor
Fixed it by doing the following:
- Added module in the library -> tsconfig
{ "compilerOptions": { ... "module": "ESNext" }, ... }
- Added module and target in spfx1 -> tsconfig
{ "extends": "../tsconfig.base.json", "compilerOptions": { ... "module": "ESNext", "target": "esnext" }, ... }
- Updated strictNullChecks in the root tsconfig.base.json to false as it was not compatible with scaffolded projects very well when using FluentUI.
- MartynowIron Contributor
Upgrade SPFx to the latest version, check for dependency conflicts in node_modules, and ensure the utility,moduleis correctly referenced in package.json.