I’v just taken over a project, which has really bad setup of vue.js with typescript. Trying to create some speed improvement but the existing webpack build (v3) didn’t allow me to do anything significant.
so i’ve updated the packages and modules to support webpack 4. Rewritten the webpack build file but come across 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
there is created d.ts file, which resolve some issues, tried awsome-typescript-loader, added typescript extensions in the resolve section etc but nothing solves the issue.
// Webpack Config
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: “../src/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’
},
},
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’)
}
]),
]
}
// TS config
{
“compileOnSave”: false,
“compilerOptions”: {
“allowSyntheticDefaultImports”: true,
“lib”: [
“es6”,
“es2017”,
“dom”,
“es2015.core”
],
“jsx”: “preserve”,
“module”: “commonjs”,
“moduleResolution”: “node”,
“noEmitOnError”: false,
“noImplicitAny”: false,
“noImplicitThis”: false,
“strict”: false,
“preserveConstEnums”: true,
“removeComments”: false,
“suppressImplicitAnyIndexErrors”: true,
“target”: “es2015”,
“baseUrl”: “./src”,
“typeRoots”: [“./src”],
“types”: [],
“outDir”: “./dist/server”,
“paths”: {
“@utils/*“: [
“utils/*“
],
“@src/*“: [
“./*“
],
“@web/*“: [
“./servers/web/vue-app/*“
],
“@shared/*“: [
“./servers/shared/*“
]
}
}
}
I’ expecting the build to complete and render out the files but these issues are preventing it
Solution :
Moved the webpack config to root folder and changed confirm to look like the below with Max pointing out Paths resolve. Which seems to work.
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’)
}
]),
]
}