Webpack is not detecting file changes

Viewed 330

I'm using Vue, with a .vue.html/.ts/.scss pattern. Each folder contains a .ts, a .vue.html and a .scss file which becomes a Vue component. Together with this I'm using Webpack.

Today, when I started working, Webpack stopped detecting .vue.html files. It now only seems to detect .ts files. Here is my webpack config:

const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
const bundleOutputDir = './wwwroot/dist';

module.exports = (env) => {
    const isDevBuild = !(env && env.prod);

    return [{
        stats: { modules: false },
        context: __dirname,
        resolve: { extensions: [ '.js', '.ts', '.d.ts' ] },
        entry: {
            'main': './ClientApp/boot.ts'
        },
        module: {
            rules: [
                { test: /\.vue\.html$/, include: /ClientApp/, loader: 'vue-loader', options: { loaders: { js: 'awesome-typescript-loader?silent=true' } } },
                { test: /\.ts$/, include: /ClientApp/, use: 'awesome-typescript-loader?silent=true' },
                { test: /\.css$/, use: isDevBuild ? ['style-loader', 'css-loader'] : ExtractTextPlugin.extract({ use: 'css-loader?minimize' }) },
                { test: /\.scss$/, use: [ 'style-loader', 'css-loader', 'sass-loader' ]},
                { test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' }
            ]
        },
        output: {
            path: path.join(__dirname, bundleOutputDir),
            filename: '[name].js',
            publicPath: 'dist/'
        },
        plugins: [
            new CheckerPlugin(),
            new webpack.DefinePlugin({
                'process.env': {
                    NODE_ENV: JSON.stringify(isDevBuild ? 'development' : 'production')
                }
            }),
            new webpack.DllReferencePlugin({
                context: __dirname,
                manifest: require('./wwwroot/dist/vendor-manifest.json')
            })
        ].concat(isDevBuild ? [
            // Plugins that apply in development builds only
            new webpack.SourceMapDevToolPlugin({
                filename: '[file].map', // Remove this line if you prefer inline source maps
                moduleFilenameTemplate: path.relative(bundleOutputDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk
            }),
        ] : [
            // Plugins that apply in production builds only
            new webpack.optimize.UglifyJsPlugin(),
            new ExtractTextPlugin('site.css')
        ])
    }];
};

I have tried running node node_modules/webpack/bin/webpack.js --watch --progress manually, which seems to detect changes correctly in .ts files, but not in .vue.html files.

Anyone with an idea what may cause this?

Here is my boot.ts:

import Vue from 'vue';
import VueRouter from 'vue-router';
import CategoriesListComponent from './components/categories-list/categories-list';
import DetailsItemComponent from './components/details-item/details-item';
import ListItemComponent from './components/list-item/list-item';
import MultiViewComponent from './components/multi-view/multi-view';
import ToolsListComponent from './components/tools-list/tools-list';
import TopMenuComponent from './components/top-menu/top-menu';
import './css/site.css';
import CategoriesListViewComponent from './views/categories-list-view/categories-list-view';
import ScanView from './views/scan-view/scan-view';
import SettingsViewComponent from './views/settings-view/settings-view';
import ToolsListViewComponent from './views/tools-list-view/tools-list-view';
import ActionButtonComponent from './components/action-button/action-button';
import InputFieldComponent from './components/input-field/input-field';
import DropDownComponent from './components/drop-down/drop-down';
import NavBarComponent from './components/nav-bar/nav-bar';
import Cookies from './data/cookies';
import ActionFieldComponent from './components/action-field/action-field';
import PushTokenHandler from './native/push-token-handler';

require('devextreme/dist/css/dx.common.css')

Vue.use(VueRouter);

Vue.component('top-menu', TopMenuComponent);
Vue.component('list-item', ListItemComponent);
Vue.component('action-button', ActionButtonComponent)
Vue.component('multi-view', MultiViewComponent);
Vue.component('tools-list', ToolsListComponent);
Vue.component('tools-list-view', ToolsListViewComponent);
Vue.component('details-item', DetailsItemComponent);
Vue.component('categories-list', CategoriesListComponent);
Vue.component('categories-list-view', CategoriesListViewComponent);
Vue.component('scan-view', ScanView);
Vue.component('settings-view', SettingsViewComponent);
Vue.component('input-field', InputFieldComponent);
Vue.component('drop-down', DropDownComponent);
Vue.component('nav-bar', NavBarComponent);
Vue.component('action-field', ActionFieldComponent);

const routes = [
    { path: '/', component: require('./pages/toolbox/toolbox-page.vue.html') },
    { path: '/scan', component: require('./pages/scan/scan-page.vue.html') },
    { path: '/toolbox', component: require('./pages/toolbox/toolbox-page.vue.html') },
    { path: '/allTools', component: require('./pages/all-tools/all-tools-page.vue.html') },
    { path: '/settings', component: require('./pages/settings/settings-page.vue.html')}
];

let router = new VueRouter({
    mode: 'history',
    routes: routes,
});

router.beforeEach((to, _, next) => {
    if (to.path !== '/settings' && Cookies.getUser() === null)
        next('/settings')
    else
        next()
});

new Vue({
    el: '#app-root',
    router: router,
    render: h => h(require('./components/app/app.vue.html'))
});

PushTokenHandler.init();

Here is a sample output:

node node_modules/webpack/bin/webpack.js --watch --progress                       0% [0] compiling
Webpack is watching the files…

[0] Hash: 4f88618dc0bfb21f1877
Version: webpack 2.7.0
Child
    Hash: 4f88618dc0bfb21f1877
    Time: 6788ms
          Asset     Size  Chunks                    Chunk Names
        main.js  1.78 MB       0  [emitted]  [big]  main
    main.js.map  2.25 MB       0  [emitted]         main
[0] Hash: f94764ec275203bd08fe
Version: webpack 2.7.0
Child
    Hash: f94764ec275203bd08fe
    Time: 877ms
          Asset     Size  Chunks                    Chunk Names
        main.js  1.78 MB       0  [emitted]  [big]  main
    main.js.map  2.25 MB       0  [emitted]         main

    ERROR in [at-loader] ./ClientApp/components/details-item/details-item.ts:5:39
        TS1005: ',' expected.

    ERROR in [at-loader] ./ClientApp/components/details-item/details-item.ts:5:5
        TS2345: Argument of type '{ props: string[]; d: any; }' is not assignable to parameter of type 'VueClass'.
      Object literal may only specify known properties, and 'props' does not exist in type 'VueClass'.

    ERROR in [at-loader] ./ClientApp/components/details-item/details-item.ts:5:39
        TS2304: Cannot find name 'd'.

    ERROR in [at-loader] ./ClientApp/components/modal/modal.ts:1:45
        TS2686: 'Vue' refers to a UMD global, but the current file is a module. Consider adding an import instead.

    ERROR in [at-loader] ./ClientApp/components/modal/modal.ts:2:4
        TS2377: Constructors for derived classes must contain a 'super' call.

You can see it update when I edit .ts file. When I edit any other file, simply nothing happens.

Here you can see "old" (not added today) .vue.html files showing up in Sources in Chrome:enter image description here

And here you can see them in Visual Studio:

enter image description here

1 Answers

It looks like you need to add '.vue.html', '.scss' to your resolve.extensions list, per the documentation.
Excerpt:

[resolve.extensions] is what enables users to leave off the extension when importing:

import File from '../path/to/file';

Using this will override the default array, meaning that webpack will no longer try to resolve modules using the default extensions.

You make sure you are either using the extensions of your .scss and .vue.html files in your components, or add them to resolve. If you are expecting import CategoriesListComponent from './components/categories-list/categories-list'; to import a Vue component, webpack needs this set up.

Related