Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save connecteev/b4271066b5cba91cb2bafc4070eb17ed to your computer and use it in GitHub Desktop.
Save connecteev/b4271066b5cba91cb2bafc4070eb17ed to your computer and use it in GitHub Desktop.
Error Moving the Spark Billing Portal (using Laravel Spark/Stripe version 4.x) from Webpack to Vite

Background

  • I've been trying to customize the UI of the laravel/spark-stripe v 4.1.2 package
  • I've been trying to move the package from vue2 to vue3, and from Webpack (Laravel mix) to Vite.
  • Later, I will want to customize part of the billing portal to look more like this.
  • But right now, I am encountering a build / front-end error that I don't know how to debug.

Here are the steps I have taken so far to move from Laravel Mix to Vite:

  1. Installed Laravel 10.x
  2. installed Laravel Breeze for Authentication, with Inertia + Vue.js (my tech stack of choice is Vue+Inertia+Laravel+TailwindCSS with Inertia SSR enabled)
  3. Installed Laravel Spark-Stripe, per the official instructions, and got it working. I installed the laravel/spark-stripe package locally in my laravel application's root directory, under {APP_URL}/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified
  4. Made the following changes to the default code (both the package and the laravel application, everything is captured in this public gist)
  5. Console Terminal 1: Ran composer install && composer update followed by php artisan migrate:fresh --seed and then php artisan serve
  6. Console Terminal 2: Ran npm install && npm update following by npm run dev
  7. Went to http://127.0.0.1:8000, registered with a new user account, logged in with that account+password
  8. Went to http://127.0.0.1:8000/billing and

Output / Error:

When I went to http://127.0.0.1:8000/billing I got a blank page, with this error in the console:

Uncaught SyntaxError: Unexpected token 'export' (at billing:483:983)

image

image

Diff of Code Changes:

Here is the full diff of all code changes I have made (both to my local laravel/spark-stripe package, and my laravel application). Note: I also have VITE_APP_NAME="${APP_NAME}" defined in my .env file

diff --git a/.env.example b/.env.example
index 655c2f2..fbec065 100644
--- a/.env.example
+++ b/.env.example
@@ -51,6 +51,7 @@ PUSHER_PORT=443
 PUSHER_SCHEME=https
 PUSHER_APP_CLUSTER=mt1
 
+VITE_APP_NAME="${APP_NAME}"
 VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
 VITE_PUSHER_HOST="${PUSHER_HOST}"
 VITE_PUSHER_PORT="${PUSHER_PORT}"
diff --git a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/package.json b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/package.json
index 561f4b1..a13b16e 100644
--- a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/package.json
+++ b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/package.json
@@ -1,24 +1,24 @@
 {
     "private": true,
     "scripts": {
-        "dev": "npm run development",
-        "development": "mix",
-        "watch": "mix watch",
-        "watch-poll": "mix watch -- --watch-options-poll=1000",
-        "hot": "mix watch --hot",
-        "prod": "npm run production",
-        "production": "mix --production"
+        "dev": "vite",
+        "build": "vite build && vite build --ssr",
+        "prod": "npm run build",
+        "production": "npm run build"
     },
     "devDependencies": {
-        "@inertiajs/vue2": "^1.0.0",
-        "autoprefixer": "^10.4.0",
-        "axios": "^0.19",
+        "@inertiajs/vue3": "^1.0.9",
+        "@vitejs/plugin-vue": "^4.0.0",
+        "@vue/server-renderer": "^3.2.31",
+        "autoprefixer": "^10.4.12",
+        "axios": "^1.1.2",
         "focus-trap": "^6.7.3",
-        "laravel-mix": "^6.0.6",
-        "postcss": "^8.4.4",
-        "tailwindcss": "^3.0.0",
-        "vue": "^2.5.17",
-        "vue-loader": "^15.9.6",
-        "vue-template-compiler": "^2.6.10"
+        "laravel-vite-plugin": "^0.7.5",
+        "postcss": "^8.4.18",
+        "tailwindcss": "^3.2.1",
+        "vite": "^4.0.0",
+        "vue": "^3.2.41",
+        "vue-loader": "^17.2.2",
+        "vue-template-compiler": "^2.7.14"
     }
 }
diff --git a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/postcss.config.js b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/postcss.config.js
new file mode 100644
index 0000000..e7e7c19
--- /dev/null
+++ b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/postcss.config.js
@@ -0,0 +1,5 @@
+module.exports = {
+    plugins: [
+        require('postcss-import'),
+    ],
+};
diff --git a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/public/build/manifest.json b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/public/build/manifest.json
new file mode 100644
index 0000000..a63c321
--- /dev/null
+++ b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/public/build/manifest.json
@@ -0,0 +1,29 @@
+{
+  "resources/css/spark.css": {
+    "file": "spark.css",
+    "isEntry": true,
+    "src": "resources/css/spark.css"
+  },
+  "resources/js/Pages/BillingPortal.vue": {
+    "css": [
+      "spark.css"
+    ],
+    "file": "BillingPortal.js",
+    "imports": [
+      "resources/js/app.js"
+    ],
+    "isDynamicEntry": true,
+    "src": "resources/js/Pages/BillingPortal.vue"
+  },
+  "resources/js/app.js": {
+    "css": [
+      "spark.css"
+    ],
+    "dynamicImports": [
+      "resources/js/Pages/BillingPortal.vue"
+    ],
+    "file": "app.js",
+    "isEntry": true,
+    "src": "resources/js/app.js"
+  }
+}
\ No newline at end of file
diff --git a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/Components/CursorPaginator.vue b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/Components/CursorPaginator.vue
index a78f829..91d3168 100644
--- a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/Components/CursorPaginator.vue
+++ b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/Components/CursorPaginator.vue
@@ -12,7 +12,7 @@
 </template>
 
 <script>
-    import { Link } from '@inertiajs/vue2';
+    import { Link } from '@inertiajs/vue3';
     import ChevronIcon from './../Icons/ChevronIcon.vue';
 
     export default {
diff --git a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/Components/PlanList.vue b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/Components/PlanList.vue
index de6cc29..056d245 100644
--- a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/Components/PlanList.vue
+++ b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/Components/PlanList.vue
@@ -17,8 +17,8 @@
 </template>
 
 <script>
-    import Plan from './../Components/Plan';
-    import SparkButton from './../Components/Button';
+    import Plan from './../Components/Plan.vue';
+    import SparkButton from './../Components/Button.vue';
 
     export default {
         components: {
diff --git a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/Components/ReceiptList.vue b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/Components/ReceiptList.vue
index c0ea63a..5cf091a 100644
--- a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/Components/ReceiptList.vue
+++ b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/Components/ReceiptList.vue
@@ -54,7 +54,7 @@
 </template>
 
 <script>
-    import CursorPaginator from './../Components/CursorPaginator';
+    import CursorPaginator from './../Components/CursorPaginator.vue';
 
     export default {
         components: {
diff --git a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/Pages/BillingPortal.vue b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/Pages/BillingPortal.vue
index 514989d..c327d6d 100644
--- a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/Pages/BillingPortal.vue
+++ b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/Pages/BillingPortal.vue
@@ -828,19 +828,19 @@
 </template>
 
 <script>
-import ErrorMessages from './../Components/ErrorMessages';
-import InfoMessages from './../Components/InfoMessages';
-import IntervalSelector from './../Components/IntervalSelector';
-import Modal from './../Components/Modal';
-import Plan from './../Components/Plan';
-import PlanList from './../Components/PlanList';
-import PlanSectionHeading from './../Components/PlanSectionHeading';
-import ReceiptList from './../Components/ReceiptList';
-import SectionHeading from './../Components/SectionHeading';
-import SparkButton from './../Components/Button';
-import SparkSecondaryButton from './../Components/SecondaryButton';
-import SuccessMessage from './../Components/SuccessMessage';
-import {router} from '@inertiajs/vue2'
+import ErrorMessages from './../Components/ErrorMessages.vue';
+import InfoMessages from './../Components/InfoMessages.vue';
+import IntervalSelector from './../Components/IntervalSelector.vue';
+import Modal from './../Components/Modal.vue';
+import Plan from './../Components/Plan.vue';
+import PlanList from './../Components/PlanList.vue';
+import PlanSectionHeading from './../Components/PlanSectionHeading.vue';
+import ReceiptList from './../Components/ReceiptList.vue';
+import SectionHeading from './../Components/SectionHeading.vue';
+import SparkButton from './../Components/Button.vue';
+import SparkSecondaryButton from './../Components/SecondaryButton.vue';
+import SuccessMessage from './../Components/SuccessMessage.vue';
+import {router} from '@inertiajs/vue3'
 
 export default {
     components: {
diff --git a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/app.js b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/app.js
index a479d60..c1c47b9 100644
--- a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/app.js
+++ b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/app.js
@@ -1,19 +1,18 @@
-window.axios = require('axios');
-window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
+import './bootstrap';
+import '../css/spark.css';
 
-import { createInertiaApp } from '@inertiajs/vue2';
-import BaseMixin from './Mixins/Base';
-import Vue from 'vue'
-
-Vue.mixin(BaseMixin);
+import { createApp, h } from 'vue';
+import { createInertiaApp } from '@inertiajs/vue3';
+import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
 
+// const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
+const appName = 'Laravel';
 createInertiaApp({
-  resolve: name => require(`./Pages/${name}`),
-  setup({ el, App, props, plugin }) {
-    Vue.use(plugin)
-
-    new Vue({
-      render: h => h(App, props)
-    }).$mount(el)
-  }
-})
+    title: (title) => `${title} - ${appName}`,
+    resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
+    setup({ el, App, props, plugin }) {
+        return createApp({ render: () => h(App, props) })
+            .use(plugin)
+            .mount(el);
+    }
+});
diff --git a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/bootstrap.js b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/bootstrap.js
new file mode 100644
index 0000000..846d350
--- /dev/null
+++ b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/resources/js/bootstrap.js
@@ -0,0 +1,32 @@
+/**
+ * We'll load the axios HTTP library which allows us to easily issue requests
+ * to our Laravel back-end. This library automatically handles sending the
+ * CSRF token as a header based on the value of the "XSRF" token cookie.
+ */
+
+import axios from 'axios';
+window.axios = axios;
+
+window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
+
+/**
+ * Echo exposes an expressive API for subscribing to channels and listening
+ * for events that are broadcast by Laravel. Echo and event broadcasting
+ * allows your team to easily build robust real-time web applications.
+ */
+
+// import Echo from 'laravel-echo';
+
+// import Pusher from 'pusher-js';
+// window.Pusher = Pusher;
+
+// window.Echo = new Echo({
+//     broadcaster: 'pusher',
+//     key: import.meta.env.VITE_PUSHER_APP_KEY,
+//     cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER ?? 'mt1',
+//     wsHost: import.meta.env.VITE_PUSHER_HOST ? import.meta.env.VITE_PUSHER_HOST : `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
+//     wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80,
+//     wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443,
+//     forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
+//     enabledTransports: ['ws', 'wss'],
+// });
diff --git a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/src/Http/Controllers/BillingPortalController.php b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/src/Http/Controllers/BillingPortalController.php
index c7bf0b0..6712e41 100644
--- a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/src/Http/Controllers/BillingPortalController.php
+++ b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/src/Http/Controllers/BillingPortalController.php
@@ -30,8 +30,8 @@ public function __invoke(Request $request, $type = null, $id = null)
         Inertia::setRootView('spark::app');
 
         View::share([
-            'cssPath' => __DIR__.'/../../../public/css/app.css',
-            'jsPath' => __DIR__.'/../../../public/js/app.js',
+            'cssPath' => __DIR__.'/../../../public/build/spark.css',
+            'jsPath' => __DIR__.'/../../../public/build/app.js',
             'translations' => static::getTranslations(),
         ]);
 
diff --git a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/src/SparkServiceProvider.php b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/src/SparkServiceProvider.php
index 3ad296d..0fd1318 100644
--- a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/src/SparkServiceProvider.php
+++ b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/src/SparkServiceProvider.php
@@ -112,6 +112,10 @@ protected function configurePublishing()
             __DIR__.'/../resources/views' => resource_path('views/vendor/spark'),
         ], 'spark-views');
 
+        $this->publishes([
+            __DIR__.'/../resources/js' => resource_path('js/vendor/spark'),
+        ], 'spark-js');
+
         $this->publishes([
             __DIR__.'/../stubs/en.json' => lang_path('spark/en.json'),
         ], 'spark-lang');
diff --git a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/vite.config.js b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/vite.config.js
new file mode 100644
index 0000000..b5695d7
--- /dev/null
+++ b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/vite.config.js
@@ -0,0 +1,43 @@
+import { defineConfig } from 'vite';
+import laravel from 'laravel-vite-plugin';
+import vue from '@vitejs/plugin-vue';
+
+// For vite config
+// See https://www.youtube.com/watch?v=L23bAMdgOZA
+// Also see https://youtu.be/VAeRhmpcWEQ?t=3895
+// See https://warrickbayman.medium.com/laravel-vue-and-inertia-with-vite-4b8b825b790a
+// Note: defineConfig helps with Intellisense
+export default defineConfig({
+    build: {
+        // outDir: 'public', // Set the desired output directory
+        // sourcemap: true,
+        emptyOutDir: true,
+        rollupOptions: {
+            output: {
+                // entryFileNames: "[name].[hash].js",
+                // chunkFileNames: "[name].[hash].js",
+                // assetFileNames: "[name].[hash].[ext]",
+                entryFileNames: "[name].js",
+                chunkFileNames: "[name].js",
+                assetFileNames: "[name].[ext]",
+            }
+        },
+    },
+    plugins: [
+        laravel({
+            input: [
+                'resources/js/app.js',
+                'resources/css/spark.css',
+            ],
+            refresh: true,
+        }),
+        vue({
+            template: {
+                transformAssetUrls: {
+                    base: null,
+                    includeAbsolute: false,
+                },
+            },
+        }),
+    ],
+});
diff --git a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/webpack.mix.js b/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/webpack.mix.js
deleted file mode 100644
index 535659b..0000000
--- a/_LOCAL_PACKAGES/spark-stripe_4.1.2_modified/webpack.mix.js
+++ /dev/null
@@ -1,19 +0,0 @@
-const mix = require('laravel-mix');
-
-/*
- |--------------------------------------------------------------------------
- | Mix Asset Management
- |--------------------------------------------------------------------------
- |
- | Mix provides a clean, fluent API for defining some Webpack build steps
- | for your Laravel application. By default, we are compiling the Sass
- | file for the application as well as bundling up all the JS files.
- |
- */
-
-mix.js('resources/js/app.js', 'public/js/app.js').vue()
-    .postCss('resources/css/spark.css', 'public/css/app.css', [
-        require('tailwindcss'),
-    ]);
-
-mix.disableSuccessNotifications();
diff --git a/vite.config.js b/vite.config.js
index 6a5d31b..531d68c 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -3,9 +3,27 @@ import laravel from 'laravel-vite-plugin';
 import vue from '@vitejs/plugin-vue';
 
 export default defineConfig({
+    build: {
+        // outDir: 'public', // Set the desired output directory
+        // sourcemap: true,
+        emptyOutDir: true,
+        rollupOptions: {
+            output: {
+                // entryFileNames: "[name].[hash].js",
+                // chunkFileNames: "[name].[hash].js",
+                // assetFileNames: "[name].[hash].[ext]",
+                entryFileNames: "[name].js",
+                chunkFileNames: "[name].js",
+                assetFileNames: "[name].[ext]",
+            }
+        },
+    },
     plugins: [
         laravel({
-            input: 'resources/js/app.js',
+            input: [
+                'resources/js/app.js',
+                'resources/css/app.css',
+            ],
             ssr: 'resources/js/ssr.js',
             refresh: true,
         }),

Other Files Added / Changed (by Build process, etc - not in the diff):

- _LOCAL_PACKAGES/spark-stripe_4.1.2_modified/.gitignore
- _LOCAL_PACKAGES/spark-stripe_4.1.2_modified/bootstrap/ssr/BillingPortal.js
- _LOCAL_PACKAGES/spark-stripe_4.1.2_modified/bootstrap/ssr/app.js
- _LOCAL_PACKAGES/spark-stripe_4.1.2_modified/composer.lock
- _LOCAL_PACKAGES/spark-stripe_4.1.2_modified/package-lock.json
- _LOCAL_PACKAGES/spark-stripe_4.1.2_modified/public/build/BillingPortal.js
- _LOCAL_PACKAGES/spark-stripe_4.1.2_modified/public/build/app.js
- _LOCAL_PACKAGES/spark-stripe_4.1.2_modified/public/build/spark.css
- _LOCAL_PACKAGES/spark-stripe_4.1.2_modified/public/css/app.css
- _LOCAL_PACKAGES/spark-stripe_4.1.2_modified/public/js/app.js
- _LOCAL_PACKAGES/spark-stripe_4.1.2_modified/public/js/app.js.LICENSE.txt
- composer.lock
- package-lock.json

How you can help / reach me

  • Leave a comment on this Laracasts thread, or
  • you may choose to leave a comment on this gist, or
  • I'm kp#2555 on Discord if you want to drop me a line there
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment