Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is this compatible with Vue SSR and Typescript? #143

Closed
sneko opened this issue Jul 10, 2020 · 7 comments
Closed

Is this compatible with Vue SSR and Typescript? #143

sneko opened this issue Jul 10, 2020 · 7 comments
Labels

Comments

@sneko
Copy link

sneko commented Jul 10, 2020

Hi @KaelWD ,

To use the "a-la-carte" feature from Vuetify I tried both things:

  • use vue add vuetify with correct settings
  • use manual yarn install as described in the documentation

I can yarn serve but as soon as I go on my page in the browser I get this fatal error:

  App running at:
  - Local:   http://localhost:3000/ (copied to clipboard)
[14:15:10] Server listening on localhost:3000
error during render url : /
/Users/XXXXXXXXXXXXXXX/node_modules/vuetify/lib/components/VIcon/index.js:1
import VIcon from './VIcon';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at compileFunction (<anonymous>)
    at wrapSafe (internal/modules/cjs/loader.js:1117:16)
    at Module._compile (internal/modules/cjs/loader.js:1165:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1221:10)
    at Module.load (internal/modules/cjs/loader.js:1050:32)
    at Function.Module._load (internal/modules/cjs/loader.js:938:14)
    at Module.require (internal/modules/cjs/loader.js:1090:19)
    at require (internal/modules/cjs/helpers.js:75:18)
    at r (/Users/XXXXXXXXXXXXXXX/node_modules/vue-server-renderer/build.dev.js:9315:16)
    at Object.vuetify/lib/components/VIcon (webpack:/external "vuetify/lib/components/VIcon":1:0)
    at __webpack_require__ (webpack/bootstrap:25:0)
    at Module../src/components/ErrorsToaster.vue (src/components/ErrorsToaster.vue:1:0)
    at __webpack_require__ (webpack/bootstrap:25:0)
    at Module../node_modules/cache-loader/dist/cjs.js?!./node_modules/ts-loader/index.js?!./node_modules/vuetify-loader/lib/loader.js?!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/Application.vue?vue&type=script&lang=ts& (js/app.js:135:87)
    at __webpack_require__ (webpack/bootstrap:25:0)
    at Module../src/Application.vue?vue&type=script&lang=ts& (src/Application.vue?b6e1:1:0)

I tried to remove VIcon references, but I got the same for VApp so I think that's a global error.

Context: I'm using Vue SSR but also Typescript. Does someone used both in the past with the vuetify-loader?

Note that I can build without trouble, the error is just when doing serve.

Thank you,

EDIT: note that after some research I tried upgrading from Node v12 to Node v13 and v14 but didn't change anything even when specifying "type": "module", in the package.json

EDIT2: since that's a SyntaxError it seems not related to Typescript so probably only due to Vue SSR 😢

@KaelWD
Copy link
Member

KaelWD commented Jul 11, 2020

Yes. Make sure you're bundling vuetify for the server too, vuetify/lib may use some features that won't work directly in node. If you're using webpack-node-externals simply add vuetify to the whitelist: https://github.com/vuetifyjs/vuetify/blob/master/packages/docs/build/webpack.server.config.js#L27

@sneko
Copy link
Author

sneko commented Jul 14, 2020

Hi @KaelWD ,

To be honest, I'm not sure to understand correctly the 2 cases described below. Note that I'm using the https://github.com/Akryum/vue-cli-plugin-ssr plugin to have SSR working.

Attempt 1

According to:
https://github.com/Akryum/vue-cli-plugin-ssr/blob/master/lib/config.js#L14
and
https://github.com/Akryum/vue-cli-plugin-ssr/blob/master/lib/webpack.js#L86

Just by using this:

module.exports = {
  productionSourceMap: false,
  transpileDependencies: [
    'vuetify',
  ],
  pluginOptions: {
    ssr: {
      criticalCSS: false,
      port: process.env.HTTP_SERVER_PORT || 3000,
      nodeExternalsWhitelist: [/\.css$/, /\?vue&type=style/, (isProd ? undefined : /^vuetify/)],
...

It should work. But it does not after building in production and trying to start the web server (serving a page results in the error described initially).

The only difference with your example is the modulesDir property that is not specified in my case (vue-cli-plugin-ssr does not allow overriding it).

Attempt 2

I decided to add also the modulesDir property but for that I need to manually customize webpack:

  configureWebpack: (config) => {
    config.externals = nodeExternals({
      whitelist: [/\.css$/, /\?vue&type=style/, isProd ? undefined : /^vuetify/],
      modulesDir: path.resolve(__dirname, '../../../node_modules'),
    });

In this case building+serving pages works but it implies a weird warning/error during the build process:

(undefined) ./node_modules/encoding/lib/iconv-loader.js 9:12-34
Critical dependency: the request of a dependency is an expression
    at CommonJsRequireContextDependency.getWarnings (/Users/XXXXXXXXXX/node_modules/webpack/lib/dependencies/ContextDependency.js:40:18)
    at Compilation.reportDependencyErrorsAndWarnings (/Users/XXXXXXXXXX/node_modules/webpack/lib/Compilation.js:1454:24)
    at /Users/XXXXXXXXXX/node_modules/webpack/lib/Compilation.js:1258:10
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/XXXXXXXXXX/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:29:1)
    at AsyncSeriesHook.lazyCompileHook (/Users/XXXXXXXXXX/node_modules/tapable/lib/Hook.js:154:20)
    at Compilation.finish (/Users/XXXXXXXXXX/node_modules/webpack/lib/Compilation.js:1253:28)
    at /Users/XXXXXXXXXX/node_modules/webpack/lib/Compiler.js:672:17
    at _done (eval at create (/Users/XXXXXXXXXX/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:7:1)
    at eval (eval at create (/Users/XXXXXXXXXX/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:42:22)
    at /Users/XXXXXXXXXX/node_modules/webpack/lib/Compilation.js:1185:12
    at /Users/XXXXXXXXXX/node_modules/webpack/lib/Compilation.js:1097:9
    at processTicksAndRejections (internal/process/task_queues.js:79:11)
 @ ./node_modules/encoding/lib/encoding.js
 @ ./node_modules/isomorphic-fetch/node_modules/node-fetch/lib/body.js
 @ ./node_modules/isomorphic-fetch/node_modules/node-fetch/index.js
 @ ./node_modules/isomorphic-fetch/fetch-npm-node.js
 @ ./src/entry-server.ts
 @ multi ./src/entry-server

I don't understand how severe this message is 🤔 . Any thoughts about it?

Thank you,

PS: sorry for not being that much confident with the webpack pipeline of Vuetify :(

EDIT: to "remove" the "Attempt 2" warning/error message, I found 2 propositions on internet:

It's indeed silenting the warning message, but when serving the pages it fails because the plugin is not here anymore 😞 (that's logic).

EDIT2: to remove this warning... the maintainer answered andris9/encoding#18 (comment) but I still don't get why putting the modulesDir brings me this message 😢

@KaelWD
Copy link
Member

KaelWD commented Jul 15, 2020

I don't think you need modulesDir, we have that because it's in a monorepo so node_modules is in a different location. If it works in dev but not production try removing the isProd ternary.

@sneko
Copy link
Author

sneko commented Jul 15, 2020

That's what I thought this property was specific to your settings... It makes absolutely no sense, see below the weird cases depending on the webpack config I use and the following script commands:

  • "ssr:build": "cross-env NODE_ENV=production vue-cli-service ssr:build",
  • "ssr:start": "cross-env NODE_ENV=production vue-cli-service ssr:serve",

Attempt 1 [FAILED]

    const whitelistPaths = [/\.css$/, /\?vue&type=style/];
    if (!isProd) {
      whitelistPaths.push(/^vuetify/);
    }

    config.externals = nodeExternals({
      whitelist: whitelistPaths,
    });
  • ssr:build works
  • ssr:start and reach the URL produces this error in the terminal:
/Users/ddXXXXXX/node_modules/vuetify/lib/components/VIcon/index.js:1
import VIcon from './VIcon';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at wrapSafe (internal/modules/cjs/loader.js:1054:16)
    at Module._compile (internal/modules/cjs/loader.js:1102:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
    at Module.load (internal/modules/cjs/loader.js:986:32)
    at Function.Module._load (internal/modules/cjs/loader.js:879:14)
    at Module.require (internal/modules/cjs/loader.js:1026:19)
    at require (internal/modules/cjs/helpers.js:72:18)
    at /Users/ddXXXXXX/node_modules/vue-server-renderer/build.prod.js:1:77673
    at Object.354e (webpack:/external "vuetify/lib/components/VIcon":1:0)
    at __webpack_require__ (webpack/bootstrap:25:0)
    at Module.eb00 (js/app.b65957f1.js:2441:14)
    at __webpack_require__ (webpack/bootstrap:25:0)
    at Object.0 (js/app.b65957f1.js:126:18)
    at __webpack_require__ (webpack/bootstrap:25:0)
    at js/app.b65957f1.js:118:18
    at Object.<anonymous> (js/app.b65957f1.js:121:10)

Attempt 2 [FAILED]

    const whitelistPaths = [/\.css$/, /\?vue&type=style/];
    if (!isProd) {
      whitelistPaths.push(/^vuetify/);
    }

    config.externals = nodeExternals({
      whitelist: whitelistPaths,
      modulesDir: path.resolve(__dirname, './node_modules'),
    });
  • ssr:build works
  • ssr:start and reach the URL produces this error in the terminal:
/Users/XXXXXXXXX/node_modules/vuetify/lib/components/VIcon/index.js:1
import VIcon from './VIcon';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at wrapSafe (internal/modules/cjs/loader.js:1054:16)
    at Module._compile (internal/modules/cjs/loader.js:1102:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
    at Module.load (internal/modules/cjs/loader.js:986:32)
    at Function.Module._load (internal/modules/cjs/loader.js:879:14)
    at Module.require (internal/modules/cjs/loader.js:1026:19)
    at require (internal/modules/cjs/helpers.js:72:18)
    at /Users/XXXXXXXXX/node_modules/vue-server-renderer/build.prod.js:1:77673
    at Object.354e (webpack:/external "vuetify/lib/components/VIcon":1:0)
    at __webpack_require__ (webpack/bootstrap:25:0)
    at Module.eb00 (js/app.78725c72.js:2441:14)
    at __webpack_require__ (webpack/bootstrap:25:0)
    at Object.0 (js/app.78725c72.js:126:18)
    at __webpack_require__ (webpack/bootstrap:25:0)
    at js/app.78725c72.js:118:18
    at Object.<anonymous> (js/app.78725c72.js:121:10)

Attempt 3 [FAILED]

    const whitelistPaths = [/\.css$/, /\?vue&type=style/];
    whitelistPaths.push(/^vuetify/);

    config.externals = nodeExternals({
      whitelist: whitelistPaths,
    });
  • ssr:build works
  • ssr:start and reach the URL produces this error in the browser:
Uncaught ReferenceError: require is not defined
    at Object.fe65 (app.9262f9e7.js:1)
    at c (app.9262f9e7.js:1)
    at Module.1e84 (app.9262f9e7.js:1)
    at c (app.9262f9e7.js:1)
    at Object.0 (app.9262f9e7.js:1)
    at c (app.9262f9e7.js:1)
    at t (app.9262f9e7.js:1)
    at app.9262f9e7.js:1
    at app.9262f9e7.js:1

Attempt 4 [SUCCESS]

    const whitelistPaths = [/\.css$/, /\?vue&type=style/];
    if (!isProd) {
      whitelistPaths.push(/^vuetify/);
    }

    config.externals = nodeExternals({
      whitelist: whitelistPaths,
      modulesDir: path.resolve(__dirname, '../../../node_modules'),
    });
  • ssr:build works
  • ssr:start works too

It also works with the modulesDir pointing to another weird path like ../../node_modules.

Note that those paths do not exist! So the only working solution for me is by targetting a non-existing directory. I'm about to loose my hair haha... I don't get anything from this situation 😿

EDIT: maybe it means that's the original externals from the SSR plugin that make everything bugging 🤔

@sneko
Copy link
Author

sneko commented Jul 15, 2020

I made it working in all cases... just switched the code to chainWepack and differenciated the target (client/server).

Here is the code:

  chainWebpack: (config) => {
    // Whitelist Vuetify files to make server side working with the Vuetify loader
    // Reference: https://github.com/vuetifyjs/vuetify-loader/issues/143
    const isClient = process.env.VUE_CLI_SSR_TARGET === 'client';
    if (!isClient) {
      // Default externals to whitelist (used by https://github.com/Akryum/vue-cli-plugin-ssr)
      const whitelistPaths = [/\.css$/, /\?vue&type=style/];

      // Add Vuetify ones
      whitelistPaths.push(/^vuetify/);

      config.externals(nodeExternals({
        whitelist: whitelistPaths,
      }));
    }
  },

You definitely showed me the right way with externals, thank you so much for helping 👍

@KaelWD
Copy link
Member

KaelWD commented Jul 15, 2020

If that works can't you just use nodeExternalsWhitelist: [/\.css$/, /\?vue&type=style/, /^vuetify/]?

@sneko
Copy link
Author

sneko commented Jul 15, 2020

Oh... yes it also work, didn't try a new time since yesterday without the isProd on this line. It simplifies things :) 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants