knpwrs / vue-node

Load vue components in node.
MIT License
62 stars 5 forks source link

Inlined images problem #7

Open neodon opened 7 years ago

neodon commented 7 years ago

Hello,

I just started tinkering with vue-node in order to run unit tests on my components without having to spin up a browser. It's pretty cool.

I'm hoping you can help me with an issue I ran into. I'm probably just doing something wrong.

Whenever I reference an image file in my component, it appears to be trying to inline the image file contents in the compiled render function. I have added the output below.

Here is the minimal test case that demonstrates the issue: https://github.com/neodon/vue-node/commit/8406b5057e75b6ae73539284f2ee2d7d1e99a964

Pardon the cross-env stuff, I just needed it for win32 support.

Can you give me any insights?


Make sure to turn on production mode when deploying for production.
See more tips at https://vuejs.org/guide/deployment.html
[Vue warn]: Error in render function: "SyntaxError: Invalid or unexpected token"

(found in <Root>)
C:\projects\vue-node\test\vue.png:1
(function (exports, require, module, __filename, __dirname) { �PNG
                                                              ^
SyntaxError: Invalid or unexpected token
    at Object.exports.runInThisContext (vm.js:73:16)
    at Module._compile (module.js:543:28)
    at Module._extensions..js (module.js:580:10)
    at extensions.(anonymous function) (C:\projects\vue-node\node_modules\require-precompiled\index.js:16:3)
    at Object.require.extensions.(anonymous function) [as .js] (C:\projects\vue-node\node_modules\ava\lib\process-adapter.js:100:4)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (C:\projects\vue-node\test\test.vue:363:18)
    at __webpack_require__ (C:\projects\vue-node\test\test.vue:20:30)
    at Proxy.render (C:\projects\vue-node\test\test.vue:194:14)
    at VueComponent.Vue._render (C:\projects\vue-node\node_modules\vue\dist\vue.runtime.common.js:3866:22)
    at VueComponent.updateComponent (C:\projects\vue-node\node_modules\vue\dist\vue.runtime.common.js:2407:21)
    at Watcher.get (C:\projects\vue-node\node_modules\vue\dist\vue.runtime.common.js:2746:25)
    at new Watcher (C:\projects\vue-node\node_modules\vue\dist\vue.runtime.common.js:2729:12)
    at mountComponent (C:\projects\vue-node\node_modules\vue\dist\vue.runtime.common.js:2411:17)
    at VueComponent.Vue$3.$mount (C:\projects\vue-node\node_modules\vue\dist\vue.runtime.common.js:7055:10)
    at Test.<anonymous> (C:\projects\vue-node\test\index.test.js:23:32)
    at Generator.next (<anonymous>)
    at step (C:\projects\vue-node\test\index.test.js:30:191)
    at C:\projects\vue-node\test\index.test.js:30:437
    at Test.<anonymous> (C:\projects\vue-node\test\index.test.js:30:99)
    at Test.__dirname [as fn] (C:\projects\vue-node\test\index.test.js:21:1)
    at Test.callFn (C:\projects\vue-node\node_modules\ava\lib\test.js:281:18)
    at Test.run (C:\projects\vue-node\node_modules\ava\lib\test.js:294:23)
    at runNext (C:\projects\vue-node\node_modules\ava\lib\sequence.js:58:44)
    at Sequence.run (C:\projects\vue-node\node_modules\ava\lib\sequence.js:90:10)
    at Concurrent.run (C:\projects\vue-node\node_modules\ava\lib\concurrent.js:41:37)
    at runNext (C:\projects\vue-node\node_modules\ava\lib\sequence.js:58:44)
    at Sequence.run (C:\projects\vue-node\node_modules\ava\lib\sequence.js:90:10)
    at runNext (C:\projects\vue-node\node_modules\ava\lib\sequence.js:58:44)
    at Sequence.run (C:\projects\vue-node\node_modules\ava\lib\sequence.js:90:10)
    at Bluebird.try (C:\projects\vue-node\node_modules\ava\lib\runner.js:214:48)
    at tryCatcher (C:\projects\vue-node\node_modules\bluebird\js\release\util.js:16:23)
    at Function.Promise.attempt.Promise.try (C:\projects\vue-node\node_modules\bluebird\js\release\method.js:39:29)
    at Runner.run (C:\projects\vue-node\node_modules\ava\lib\runner.js:214:22)
    at process.on.options (C:\projects\vue-node\node_modules\ava\lib\main.js:82:10)
    at emitOne (events.js:96:13)
    at process.emit (events.js:189:7)
    at process.on.message (C:\projects\vue-node\node_modules\ava\lib\process-adapter.js:14:10)
    at emitTwo (events.js:106:13)
    at process.emit (events.js:192:7)
    at process.nextTick (internal/child_process.js:757:12)
    at _combinedTickCallback (internal/process/next_tick.js:67:7)
    at process._tickCallback (internal/process/next_tick.js:98:9)

  3 passed
  1 failed

  renders the correct message
  C:\projects\vue-node\test\index.test.js:24

   23:   const vm = new Constructor().$mount();
   24:   t.is(vm.$el.querySelector('h1').textContent, 'Hello, World!');
   25:   // Update

  Rejected promise returned by test

  Rejection reason:

    [TypeError: vm.$el.querySelector is not a function]

  Test.<anonymous> (test/index.test.js:24:15)
  step (test/index.test.js:30:191)
  Test.<anonymous> (test/index.test.js:30:99)
  Test.__dirname [as fn] (test/index.test.js:21:1)

events.js:161
      throw er; // Unhandled 'error' event
      ^

Error: spawn ava ENOENT
    at notFoundError (C:\projects\vue-node\node_modules\cross-spawn\lib\enoent.js:11:11)
    at verifyENOENT (C:\projects\vue-node\node_modules\cross-spawn\lib\enoent.js:46:16)
    at ChildProcess.cp.emit (C:\projects\vue-node\node_modules\cross-spawn\lib\enoent.js:33:19)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:215:12)
error Command failed with exit code 1.```
neodon commented 7 years ago

I think I figured out a way to resolve this issue. By default vue-loader will transform img src and image href attributes to require expressions. This can be disabled with the transformToRequire option: https://github.com/vuejs/vue-loader/blob/master/docs/en/options.md#transformtorequire

Here is the change I made to pass the test case: https://github.com/neodon/vue-node/commit/3312b6af5b5e9091720b6fc84a4876a6cae390d1

I understand this is a change the users of your module would have to make in their webpack config. Do you think it could be useful to mention it in the README?

Thanks for hearing me out.

knpwrs commented 7 years ago

Transforming image tags to use require statements is a feature of html-loader which is used by vue-loader. It's actually very common to leave this on because then webpack is able to manage all of your assets which gives you really powerful features. If you are referencing svgs, for instance, you can use svgo-loader to optimize them. Other loaders will let you optimize other image types. Chaining with the file-loader will make webpack output files in the destination directory and url-loader will let you inline resources into your JavaScript bundle. Other benefits include failing your build if an asset is missing.

It is my experience that you should let webpack manage all of your assets so you don't have to. Is there a reason why you don't want webpack to manage your assets? If you build your application without letting webpack manage your assets it's up to you to make sure they are in place correctly.

If you turn off that option you turned on and set up either file-loader or url-loader for the pattern/\.png$/ you should be good to go.

neodon commented 7 years ago

Thank you for the quick response and extra information. I agree with you and would much prefer to leave the require statements enabled. I am only doing this for unit tests though, so it's a viable work-around at the moment.

I have already tried setting up file-loader and url-loader for png files. I have also tried ignore-loader and encountered the same problem.

While trying to add some logging and having the log messages treated as bad source code by the compiler, it occurred to me that the issue might be related to the way compiled output is being passed through stdout. You should be able to reproduce the error from my initial message even when using alternative loaders.