AiverReaver
AiverReaver

Reputation: 164

How to use Typescript in Laravel Project with Vue as frontend?

I want to use typescript in Vue in Laravel project.

I already checked all tutorials for that but none of them works for me give below teej. Titas Gailius. sebastiandedeyne.

when ever i run 'npm run dev' i get this error

    ERROR in ./resources/js/app.ts
   Module build failed: Error: You may be using an old version of webpack; please check you're using at least version 4
at successfulTypeScriptInstance (E:\PersonalProjects\web_dev\blog\node_modules\ts-loader\dist\instances.js:144:15)
at Object.getTypeScriptInstance (E:\PersonalProjects\web_dev\blog\node_modules\ts-loader\dist\instances.js:34:12)
at Object.loader (E:\PersonalProjects\web_dev\blog\node_modules\ts-loader\dist\index.js:17:41)
 @ multi ./resources/js/app.ts ./resources/sass/app.scss

Upvotes: 3

Views: 10254

Answers (1)

AiverReaver
AiverReaver

Reputation: 164

Im facing this problem from quite some days but i was finally be able to find the solution for that so im Sharing my exp to folks who want to use typescript instead of javascript in vue in laravel. so here is the instruction

here the intruction

Laravel 5.7 uses Laravel-mix which down the line uses webpack 3 . Which is not what we want for typescript to work in laravel project.

Initialize your project

Let's create a new Project. You can also do this on Existing project just make sure to convert js code to ts.

First make sure you have composer and laravel installed

sh laravel new Laravel-Vue-Typecript Open the project in your any favraite code editor.

Open the package.json and add these packages to devdependencies

{
   "devDependencies": {
        "auto-loader": "^0.2.0",
        "autoprefixer": "^9.4.1",
        "axios": "^0.18",
        "bootstrap": "^4.0.0",
        "lodash": "^4.17.5",
        "popper.js": "^1.12",
        "jquery": "^3.2",
        "cross-env": "^5.1",
        "css-loader": "^1.0.1",
        "mini-css-extract-plugin": "^0.4.5",
        "node-sass": "^4.10.0",
        "optimize-css-assets-webpack-plugin": "^5.0.1",
        "postcss-loader": "^3.0.0",
        "sass-loader": "^7.1.0",
        "ts-loader": "^5.3.1",
        "typescript": "^3.2.1",
        "uglifyjs-webpack-plugin": "^2.0.1",
        "vue": "^2.5.17",
        "vue-class-component": "^6.3.2",
        "vue-property-decorator": "^7.2.0",
        "webpack": "^4.26.1",
        "webpack-cli": "^3.1.2",
        "vue-loader": "^15.4.2",
        "vue-template-compiler": "^2.5.17"
    }
}

Now install these npm packages with

npm install

Add Typescript Support

Then rename these files

Laravel-Vue-Typecript/
├─ resources/js/app.js => resources/js/app.ts
└─ resources/js/bootstrap.js => resources/js/bootstrap.ts

Now Change the Code in app.ts, bootstrap.ts and

resources/js/components/ExampleComponent.vue

// app.ts
import "./bootstrap"
import Vue from "vue"
import ExampleComponent from "./components/ExampleComponent.vue"

Vue.component('example', ExampleComponent)

new Vue({
    el: '#app'
})



// bootstrap.ts
import axios from 'axios';
import * as _ from 'lodash';
import jQuery from 'jquery';
import * as Popper from 'popper.js';
import 'bootstrap';

axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';


let token : HTMLMetaElement | null = document.head!.querySelector('meta[name="csrf-token"]');

if (token) {
    axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}


// resources/js/components/ExampleComponent.vue
<template>
    <h1>This is an example component</h1>
</template>

<script lang="ts">
import Vue from 'vue'
import Component from "vue-class-component"
@Component
export default class ExampleComponent extends Vue {
    mounted() : void {
        console.log("hello");
    }
}
</script>

``` Create typings.d.ts file inside resources/js and add these lines.

declare module '*.vue' {
    import Vue from 'vue'
    export default Vue
}

declare module 'jquery';

declare module 'lodash';

Now Create tsconfig.json, webpack.config.js and postcss.config.js in the root of your project and these lines of code to them respectivly

tsconfig.json

{
    "compilerOptions": {
        "target": "es5",
        "strict": true,
        "module": "es2015",
        "moduleResolution": "node",
        "experimentalDecorators": true,
        "skipLibCheck": true
    },
    "include": [
        "resources/js/**/*"
    ],
    "exclude": [
        "node_modules",
        "vendor"
    ]
}

webpack.config.json

const path = require('path')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const autoprefixer = require('autoprefixer');
const webpack = require('webpack');


let env = process.env.NODE_ENV
let isDev = env === 'development'

const WEBPACK_CONFIG = {
    mode: env,
    entry: {
        app: ['./resources/js/app.ts', './resources/sass/app.scss'],
    },
    output: {
        publicPath: './public',
        path: path.resolve(__dirname, 'public'),
        filename: 'js/[name].js',
        chunkFilename: 'js/chunks/app.js'

    },
    module: {
        rules: [{
                test: /\.tsx?$/,
                loader: 'ts-loader',
                options: { appendTsSuffixTo: [/\.vue$/] },
                exclude: /node_modules/,
            },
            {
                test: /\.vue$/,
                loader: 'vue-loader'
            },
            {
                test: /\.scss$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader',
                    'sass-loader'
                ],
                exclude: /node_modules/,
            }
        ],
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'css/[name].css'
        }),
        new VueLoaderPlugin(),
        new webpack.LoaderOptionsPlugin({
            options: {
                postcss: [
                    autoprefixer()
                ]
            }
        })

    ],
    resolve: {
        extensions: ['.js', '.jsx', '.vue', '.ts', '.tsx'],
        alias: {
            vue$: 'vue/dist/vue.esm.js',
        },
    },
    optimization: {
        splitChunks: {
            chunks: 'async',
            minSize: 30000,
            maxSize: 0,
            minChunks: 1,
            maxAsyncRequests: 5,
            maxInitialRequests: 3,
            automaticNameDelimiter: '~',
            name: true,
            cacheGroups: {
                vendors: {
                    test: /[\\/]node_modules[\\/]/,
                    priority: -10
                },
                default: {
                    minChunks: 2,
                    priority: -20,
                    reuseExistingChunk: true
                }
            }
        }
    }


}

if (!isDev) {
    WEBPACK_CONFIG.optimization = {
        minimizer: [
            new UglifyJsPlugin({
                cache: true,
                parallel: true,
                sourceMap: true
            }),
            new OptimizeCSSAssetsPlugin({})
        ]
    }

    WEBPACK_CONFIG.plugins.push(
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: 'production'
            }
        })

    )
}

module.exports = WEBPACK_CONFIG

postcss.config.js

 module.exports = {
     plugins: {
         'autoprefixer': {}
    } }

Now finally change the "scripts" in package.json

"scripts": {
        "dev": "npm run development",
        "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=webpack.config.js",
        "watch": "npm run development -- --watch",
        "watch-poll": "npm run watch -- --watch-poll",
        "prod": "npm run production",
        "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=webpack.config.js"
    },

Finally build the project

and run the npm scripts by npm run dev // To build the Project npm run watch // To build and watch for files changes and build automagically npm run prod // for production

Upvotes: 3

Related Questions