The module resolution issue in Webpack4 when using TypeScript

I have recently taken over a project that had a poorly configured Vue setup with TypeScript. I am attempting to make some performance improvements, but the current webpack build (v3) is limiting my progress.

After updating the packages and modules to support webpack 4, I rewrote the webpack build file only to encounter this issue:

ERROR in ./servers/web/vue-app/router.ts
Module not found: Error: Can't resolve '@web/features/home' in '/Users/username/Documents/repo/prism/src/servers/web/vue-app'
@ ./servers/web/vue-app/router.ts 23:13-42
@ ./servers/web/vue-app/application.ts
@ ./servers/web/vue-app/index.ts

I have tried creating a .d.ts file to address some issues, experimented with awesome-typescript-loader, added TypeScript extensions in the resolve section, but none seem to solve the problem.

// Adjusted Webpack Configuration 
const path = require('path');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const { isProduction, workingDirectory, isDevelopment } = require('../build/environment')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');

// Rest of the webpack configuration remains unchanged...

// Adjusted TS Configuration     
{
    "compileOnSave": false,
    // Updated compiler options...
}

I had hoped that the modifications would allow the build to complete and generate the necessary files, but these persistent issues are hindering progress.

Answer №1

Relocated the webpack configuration to the root directory and modified it as suggested by Max regarding Paths resolve, which appears to be effective.

const path = require('path');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const { isProduction, workingDirectory, isDevelopment } = require('./build/environment')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');

module.exports = {
    mode: 'production',
    context: path.resolve(__dirname, 'src'),
    entry:{
        vendor: [
            'babel-polyfill',
            'braintree-web',
            'change-case',
            'jquery',
            'materialize-css',
            'moment',
            'numeral',
            'vee-validate',
            'vue',
            'vue-resource',
            'vue-router',
            'vue-scrollto',
            'vue-cookie',
            'vuex',
            'vuex-router-sync'
          ],
       main: "./servers/web/vue-app/index.ts",
    },
    output: {
        path:  path.resolve(__dirname, 'dist/client'),
        filename:'[chunkhash].client.js',
        publicPath: process.env.HOST_STATIC,
    },
    module: {
        rules:[
            {
                test: /\.js$/,
                exclude:/node_modules/,
                loader: "babel-loader",
                options: {
                    presets: ["@babel/preset-env"]
                },
            },
            {
                test: /\.vue$/,
                loader: 'vue-loader',
            },
            {
                test: /\.html$/,
                use: [
                  // apply multiple loaders and options
                  "htmllint-loader",
                  {
                    loader: "html-loader",
                  }
                ]
            },
            {
                test: /\.ts$/,
                exclude: /node_modules/,
                use: [{
                  loader: "babel-loader",
                    options: {
                        presets: ["@babel/preset-env"]
                    },
                  },
                  {
                  loader: 'ts-loader',
                  options: {
                      appendTsSuffixTo: [/\.vue/]
                  }
                }],
            },  {
                test: /\.scss$/,
                use: [   
                "style-loader", // creates style nodes from JS strings
                "css-loader", // translates CSS into CommonJS
                "sass-loader" // compiles Sass to CSS, using Node Sass by default],
                ]
            }, {
                test: /\.css$/,
                use: [
                  {
                    loader: MiniCssExtractPlugin.loader,
                    options: {
                      // you can specify a publicPath here
                      // by default it uses publicPath in webpackOptions.output
                      publicPath: '../',
                      hmr: process.env.NODE_ENV === 'development',
                    },
                  },
                  'css-loader',
                ],
              }
        ],
    },
    resolve: {
        // options for resolving module requests
        // (does not apply to resolving to loaders)
        modules: ['node_modules'],
        // directories where to look for modules
        extensions: [ ".js",".ts", ".vue"],
        alias: {
            vue$: 'vue/dist/vue.esm.js',
            '@utils': path.resolve(__dirname,'src/utils/'),
            '@src': path.resolve(__dirname,'src/'),
            '@web': path.resolve(__dirname, 'src/servers/web/vue-app/'),
            '@shared': path.resolve(__dirname, 'src/servers/shared/'),
        },
      },
    optimization: {
        mergeDuplicateChunks: false,
        splitChunks: {
            // include all types of chunks
            chunks: 'all'
        },
        minimizer: [new UglifyJsPlugin()]

    },
      performance: {
        hints: "warning", // enum
        maxAssetSize: 100000, // int (in bytes),
        maxEntrypointSize: 400000, // int (in bytes)
        assetFilter: function(assetFilename) {
          // Function predicate that provides asset filenames
          return assetFilename.endsWith('.css') || assetFilename.endsWith('.js');
        }
      },
      devtool: "source-map",
      target: "web", // enum
      externals: ["jQuery", "Vue", "Typescript"],
      // Don't follow/bundle these modules, but request them at runtime from the environment
      // lets you provide options for webpack-serve
      stats: "errors-only",
      // lets you precisely control what bundle information gets displayed
      devServer: {
        contentBase: path.join(__dirname, 'public'), // boolean | string | array, static file location
        compress: true, // enable gzip compression
        historyApiFallback: true, // true for index.html upon 404, object for multiple paths
        hot: true, // hot module replacement. Depends on HotModuleReplacementPlugin
        https: true, // true for self-signed, object for cert authority
        noInfo: true, // only errors & warns on hot reload
      },
      plugins: [
        new VueLoaderPlugin(),
        new VueSSRClientPlugin({
            filename: '../asset-manifest.json'
        }),
        new MiniCssExtractPlugin({
            filename: isDevelopment ? '[name]-style.css' : '[hash]/[name]-style.css',
            chunkFilename: '[id].css',
          }),
        new OptimizeCssAssetsPlugin({
            cssProcessorOptions: { discardComments: { removeAll: true } },
            canPrint: true
          }),
        new CopyWebpackPlugin([
            {
              from: path.resolve(workingDirectory, 'src', 'servers', 'web', (isProduction ? 'production-robots.txt' : 'pre-production-robots.txt')),
              to: path.resolve(workingDirectory, 'dist', 'server', 'client',  'robots.txt')
            }
          ]),
      ]
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

vue-spa breadcrumbs component

I am currently working on enhancing the navigation of my vue-spa project by implementing breadcrumbs. These breadcrumbs should be capable of displaying properties as breadcrumb-items, and each part of a route must be correctly identified as a breadcrumb-it ...

Observable not defined in facade pattern with RxJS

(After taking Gunnar's advice, I'm updating my question) @Gunnar.B Tool for integrating with API @Injectable({ providedIn: 'root' }) export class ConsolidatedAPI { constructor(private http: HttpClient) { } getInvestments(search?: ...

Angular - Karma Testing - Error: Unable to access property 'textContent' of undefined

I encountered an issue while running 'ng test' on my Angular 6 application: Error: Unable to access property 'textContent' of null To view a sample of the application, please check out: SampleApp The problem seems to be originatin ...

Click event for a tree component in Angular 2

How can I trigger a node click event in an Angular tree component? import { TREE_ACTIONS, KEYS, IActionMapping } from 'angular2-tree-component'; const actionMapping:IActionMapping = { mouse: { click: TREE_ACTIONS.TOGGLE_SELECTED_MULTI } ...

Combinations of Typescript dependent unions

I'm struggling with calling the given union that wraps a function and its argument. Is there a way to call it without having to cast? type Wrapper = { fn: (a: string) => void arg: string } | { fn: (a: number) => void arg: number } let f ...

Is it possible to utilize tsc --watch exclusively for type checking alongside esbuild?

When I execute tsc --noEmit --incremental, it takes approximately 17 seconds to complete. To improve the speed, tsc provides watch mode which now only takes around 2 seconds. This is my current script: // type checking tsc --noEmit --incremental // build ...

Unlock the power of two-way data binding in Vuex using the mapGetter helper

Understanding how Vuex utilizes two-way data binding involves using set() and get() methods on the computed property of the component. This means returning the store state or relevant getter in the get() method, then committing a mutation in the set method ...

Filtering object values in Typescript based on specific keys

Here is a JSON object: { "A": " ", "B": "x", "C": " " } I am trying to extract specific values in array form like this: ["A", "C"] This array represents the keys from the o ...

What are the reasons behind my inability to install certain packages using npm?

After using npm, I realized that there are times when packages cannot be installed. For example, while I am able to install jquery with the regular npm command npm install jquery, I encounter an error when trying to install webpack-watch-server using the c ...

In Vue js, where is the best place to incorporate something similar to a 'base.html' template?

My transition from a Flask backend without a front end framework to Vue.js (with no chosen backend yet) has me considering how to structure my project. Previously, I would create a 'base.html' file that contained all the necessary HTML code, depe ...

Using Vue.js: Load component only after user's button click

I need some help with my code setup. I want to make it so that the components "dataPart1' and "dataPart2" are not loaded by default, but only appear when a user presses a button to view the data. How can I achieve this functionality in Vue.js? var ap ...

"Error TS2339: The property specified does not exist within type definition", located on the input field

When a user clicks a specific button, I need an input field to be focused with its text value selected entirely to allow users to replace the entire value while typing. This is the markup for the input field: <input type="text" id="descriptionField" c ...

Testing Playwright - accessing variables from the .env file

I am currently working on a Playwright test script in TypeScript and I'm looking for a way to leverage variables from my .env file within the test. Does anyone know how this can be accomplished? ...

There was an issue with the rendering: "TypeError: Unable to access the property 'text' because it is undefined"

There is an issue when it comes to rendering the content.link.text property in this code. It shows a Error in render: "TypeError: Cannot read property 'text' of undefined", although there are no errors when passing the title and description. Par ...

To retrieve a property in Vue, you can use either the "this" keyword

Exploring Vue for the first time and navigating through accessing viewmodel data has me puzzled. When should I utilize this.property versus vm.$data.property. In this scenario with a table where I can select rows, there are methods in place to select all ...

Populate object values dynamically through function invocations

Currently, I am involved in a project with a VueJS application that incorporates the following helper class and method: class BiometricMap { static get(bioType) { if (!bioType) { return BiometricMap.default(); } const bioTypes = { ...

Unable to pass property to child component

When trying to pass a string array prop in my child component, I encountered an error message: "Cannot destructure property 'taskList' of 'this.state' as it is null.". This error occurred when using destructurization. What am ...

Is there a way to separate a string using two different delimiters?

Here is my code snippet : <template> ... <p v-for="club in clubs">{{club}}</p> ... </template> <script> export default { data: () => ({ clubs: '' }), mounted () { let dataClub = "- ...

Looking for the specific data changes in Vue.js that trigger a component to re-render?

When working with Vue.js, I've noticed that components re-render (update) when data changes. However, there are times when this re-rendering happens too frequently. I'm looking for a way to identify which specific data changes are triggering thes ...

Unable to locate the slim JWT token in the axios request

Currently, I am in the process of creating a Vue js/Vuetify website that utilizes a PHP Slim Framework API with tuuopla slim-jwt-auth serving as the middleware for JWT token authentication. While the unprotected routes are functioning correctly, I have enc ...