# My personal tips how to configure a SPFx project after creation

It is very easy to create a new SPFx project and you can find a lot of posts about it. One of these posts is, of course, the one from [Microsoft](https://learn.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/get-started/build-a-hello-world-web-part). But what should you do after the "empty" project is created?

I will describe what **I personally** do after I create a new project. Some steps may not be relevant for you because you prefer a different way of working or structure your project differently. But maybe there's one or two things you didn't know yet and think it's good.

> NOTE: In the meantime, I have developed a CLI that automates the settings mentioned here and more for you. [Read more](https://spfx-app.dev/my-cli-for-spfx-development)

## SPFx fast serve

I have often mentioned that I like the npm package [spfx-fast-serve](https://github.com/s-KaiNet/spfx-fast-serve) developed by [Sergei Sergeev](https://github.com/s-KaiNet). If you don't know it, you must use it! So the first step I do after creating the project is to run the `spfx-fast-serve` command in my terminal. This is of course only possible if you have installed the package globally before. After running the command, the tool prompts you to run the `npm install` command again. Since [I switched to pnpm](https://spfx-app.dev/using-pnpm-in-spfx-projects), of course, I have to run `pnpm install`

## Configure (path) Alias

Most use relative paths to refer to files from the solution. Here are a few examples:

```TypeScript
import HelloWorldWebPartComponent from './components/HelloWorldWebPartComponent';
import { MyComponent } from '../../components/MyComponent';
```

Custom aliases allow you to create (mostly) shorter and more intuitive paths for your imports. This is especially beneficial in larger projects where multiple levels of folder structures can lead to unwieldy (relative) paths. But it is also helpful if you want to reuse the modules later because then you don't have to work with the relative paths anymore. Here is the same example as above, but with the alias:

```TypeScript
import HelloWorldWebPartComponent from ' @webparts/helloworld/components/HelloWorldWebPartComponent';
import { MyComponent } from '@components/MyComponent';
```

### Extending tsconfig.json with baseUrl and custom Alias

The `tsconfig.json` file is the configuration file for TypeScript projects and provides various options to control the behavior of the TypeScript compiler. By extending this file in your SPFx solution, you can better customize the TypeScript compilation process to suit your project structure and needs.

#### 1\. Adding baseUrl

The `baseUrl` property in `tsconfig.json` allows you to set a base directory for module resolution. This means you can define a central starting point for your imports, reducing the need for long relative paths.

For example, by including a `baseUrl` property pointing to your project's `src` directory, you establish a foundation for cleaner, more intuitive imports. But I personally point to `'.'`. Here is an example of how the file `tsconfig.json` looks like after the change:

```json
"compilerOptions": {
  "baseUrl": ".",
  // Other options...
}
```

#### 2\. Defining Aliases

To create a custom alias, add the `paths` property under `compilerOptions` in your `tsconfig.json`. This property maps aliases to their corresponding paths.

I always create an alias for the `src` folder (that's why my `baseUrl` points to `'.'` and not `'src'`), the `webparts` folder and the `components` folder. But of course, you can also create your own alias. This is how the `tsconfig.json` looks like after the change:

```json
{
  "extends": "./node_modules/@microsoft/rush-stack-compiler-4.5/includes/tsconfig-web.json",
  "compilerOptions": {
    // Other options...
    "paths": {
      "@src/*": ["src/*"],
      "@components/*": ["src/components/*"],
      "@webparts/*": ["src/webparts/*"]
    },
    "baseUrl": "."
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx"
  ]
}
```

### Registering custom aliases in Gulp

After defining aliases in your `tsconfig.json`, you must ensure they work during the build process. This involves syncing the aliases with the build output.

In your `gulpfile.js`, before the `build.initialize(require('gulp'));` code part, add this:

```JavaScript
build.configureWebpack.mergeConfig({
    additionalConfiguration: (generatedConfiguration: any) => {
      if (!generatedConfiguration.resolve.alias) {
        generatedConfiguration.resolve.alias = {};
      }  

      // webparts folder
      generatedConfiguration.resolve.alias['@webparts'] = path.resolve(
        __dirname,
        'lib/webparts'
      );  

      // components folder
      generatedConfiguration.resolve.alias['@components'] = path.resolve(
        __dirname,
        'lib/components'
      );

      //root src folder
      generatedConfiguration.resolve.alias['@src'] = path.resolve(
        __dirname,
        'lib'
      );  

      return generatedConfiguration;
    }
});
```

Make sure that you have added the `path` package to the beginning of your `gulpfile.js`

```JavaScript
const path = require('path');
```

> NOTE: In gulpfile, you should use the `lib` folder instead of `src`.

### Registering custom aliases in spfx-fast-serve

After running the command `spfx-fast-serve` in your terminal (described above), the command added a new folder in the root of your project, called `fast-serve`, containing a file called `webpack.extend.js`. Again, we need to register the alias so `webpack` can resolve it.

There should be an (empty) variable `webpackConfig` in the file:

```JavaScript
const webpackConfig = {
}
```

Now you have to extend this and register your alias:

```JavaScript
const path = require('path');
const webpackConfig = {
  /* CUSTOM ALIAS START */
  resolve: {
      alias: {
        "@webparts": path.resolve(__dirname, "..", "src/webparts"),
        "@components": path.resolve(__dirname, "..", "src/components"),
        "@src": path.resolve(__dirname, "..", "src"),
      }
  },
  /* CUSTOM ALIAS END */
}
```

> NOTE: In `webpack.extend.js` you should use the `src` path again. And because the file is in a folder, you need to add a `'..'` after `__dirname` when calling the `path.resolve` method. And again, do not forget to import the path package!

That's it, now you can use your defined alias instead of relative paths!

## Create Gulp task to increase the (package) version

If you want to have a command to increment the SPFx solution version (`config/package-solution.json`) and the `package.json` version, then you should define a custom gulp task like I do. And even more, if you want to build the solution, increase the version and package the solution with one command, [then you should read my post on how to do that](https://spfx-app.dev/package-spfx-solution-with-one-command-and-automatically-increase-the-version).

## Optional steps

I know the following steps aren't relevant to everyone or may not even appeal, but these are the ones I always do!

### Disable CSS class name warnings

I often use CSS class names that do not conform to the Microsoft schema and are not camlCase. An example would be `spfxappdev-grid`.

When I define this, I get a warning

> Warning - \[sass\] The local CSS class 'spfxappdev-grid' is not camelCase and will not be type-safe.

To remove this warning, you can suppress it in `gulpfile.js`. An SPFx project even suppresses such a warning for Microsoft's own CSS class by default. You can find it in the `gulpfile.js`

```JavaScript
build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);
```

Of course, I could now add a new suppression by entering the following

```JavaScript
build.addSuppression(`Warning - [sass] The local CSS class 'spfxappdev-grid' is not camelCase and will not be type-safe.`);
```

But I won't. Because I have more than just this one class. To suppress all these messages you can use RegEx:

```JavaScript
build.addSuppression(/Warning - \[sass\] The local CSS class/gi);
```

That's it!

### Change ESLint Rules / TypeScript rules

Since SPFx v.1.15 was released, Microsoft switched from TSLint to ESLint. Actually a good decision, but some rules annoy me personally. Especially if you use `spfx-fast-serve` and you are still developing the modules. Sometimes you just want to test something fast and define variables that are not used (yet). Or you comment out a code and the method is now "empty". Then errors are output and often the `spfx-fast-serve` process is stopped =&gt; you have to start it again after fixing.

For this reason, I change the rules before starting development. To change them, open your `.eslintrc.js` and set your own values. For example, I change these rules to `0` (`0` = '0ff', `1` = 'warning', `2` = 'error'):

```JavaScript
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/no-floating-promises': 0,
'@typescript-eslint/no-unused-vars': [
          0,
          {
            vars: 'all',
            // Unused function arguments often indicate a mistake in JavaScript code.  However in TypeScript code,
            // the compiler catches most of those mistakes, and unused arguments are fairly common for type signatures
            // that are overriding a base class method or implementing an interface.
            args: 'none',
          },
]
```

And then I also change the `tsconfig.json`. I add these `compilerOptions`:

```json
"compilerOptions": {
	// Other options...
    "noImplicitAny": false,
    "noUnusedLocals": false,
    "noUnusedParameters": false,
}
```

By the way, [here is](https://www.voitanos.io/blog/sharepoint-framework-v1.15-and-the-attack-of-eslint/) a good article if you want to learn more about ESLint with SPFx.

## I don't have to do this every time, thanks to my CLI

Since I have done these above steps every time, for every project, I wanted to simplify it a bit. So I developed [my own command line interface (CLI)](https://www.npmjs.com/package/@spfxappdev/cli) that does just that ([Read more about my CLI](https://spfx-app.dev/my-cli-for-spfx-development)).

## This is my typical folder structure

It has less to do with the topic of the article, but maybe someone is interested in what my folder structure looks like, which I (almost always) create. Of course not immediately, but only when I need it.

```bash
src
|- models
     |- interfaces
|- services
|- components
|- webparts
     |- components
|- ...
```

The `components` folder directly in the `src` folder is only for components I use in further SPFx modules (e.g. if I have more than one webpart or extension).

## That's it

I hope you enjoyed the article and got some helpful tips. I would also be happy about feedback. Gladly also with your tips :)

Happy coding :)
