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

Marko and webpack #44

Closed
maxwarch opened this issue Mar 3, 2015 · 21 comments
Closed

Marko and webpack #44

maxwarch opened this issue Mar 3, 2015 · 21 comments

Comments

@maxwarch
Copy link

maxwarch commented Mar 3, 2015

Hello,
is there a way to work with marko and webpack, a marko-loader perhaps ?
Thanks

@patrick-steele-idem
Copy link
Contributor

Short answer

Yes, you can use Marko with webpack. You just need to enable the markoify Browserify transform for webpack: https://github.com/raptorjs/marko#using-browserify

To use a browserify transform with webpack you can use the following webpack loader: https://github.com/webpack/transform-loader

In theory, it would probably be trivial to build a custom Marko loader for webpack, but it is not something we have plans to do. If you or someone else wants to introduce a marko-loader for webpack I'm sure that would be helpful to others.

Long answer

Marko templates compile down to standard CommonJS JavaScript modules. If you pre-compile all of your templates, then the following code will always work with webpack or any other JavaScript module loader:

var template = require('marko').load(require('./template.marko.js'));

You can pre-compile your templates using the markoc command line utility. For example:

markoc .

Pre-compilation is kind of a pain since you need to typically set up a file watching service (or Gulp/Grunt build script) compile on templates on change, but it works.

To avoid pre-compilation, we recommend the following code to load a template:

var template = require('marko').load(require.resolve('./template.marko'));

That code will work on the server-side no problem, but Browserify and WebPack do not recognize and support require.resolve so you must use a Browserify transform to compile the Marko template automatically and transform the code to the following:

var template = require('marko').load(require('./template.marko.js'));

That's exactly what the following Browserify transform does for you: https://github.com/raptorjs/markoify


I hope that answers your question.

As a side note, you might want to consider using the optimizer since it is more feature-rich JavaScript module bundler that also supports CSS, code splitting, bundling, lazy loading, etc.

@maxwarch
Copy link
Author

maxwarch commented Mar 3, 2015

Thanks, i will try !

@KateKate
Copy link

KateKate commented Jul 9, 2015

@maxwarch Hi! Have you succeed with webpack and marko? I'd tried it and encountered the problem that webpack 'Cannot find module 'raptor-logging-impl''. Direct installation of 'raptor-logging-impl' doesn't help. Will be nice to get your feedback. Thanks!

@maxwarch
Copy link
Author

maxwarch commented Jul 9, 2015

@KateKate hi, unfortunately i haven't the time to try this. I hope i will have !

@patrick-steele-idem
Copy link
Contributor

I've not tried using marko with webpack, but I suspect that the webpack bundler is choking due to the following lines: https://github.com/raptorjs/raptor-logging/blob/b5045817e413e29077fa6fc7ac9de3243167c679/lib/raptor-logging.js#L1-L7

I'm not sure what to suggest in this case, because it seems like a bug in webpack since lasso and browserify have no issues. If anyone knows of a workaround for webpack please share.

@KateKate
Copy link

KateKate commented Jul 9, 2015

@patrick-steele-idem thank you for your feedback.

@wheresrhys
Copy link

It's a bit of a hack, but if a module uses process and it's bundled by webpack then webpack (and browserify) sets process.browser: true. So if the try/catches in raptor and marko's src are only there for the benefit of browserify then replacing them with if(!process.browser) would mean the code compiles properly in webpack too @patrick-steele-idem

@wheresrhys
Copy link

I've found, and found a potential workaround for, another bug in webpack.

Because, I guess, it places a higher importance on loading files with extensions other than .js webpack tries to load mypartial.marko rather than mypartial.marko.js when using <include in any template. The workaround I found is to compile <include to e.g. __loadTemplate(require("../../components/nav/tpl.marko.js"), require) instead of __loadTemplate(require.resolve("../../components/nav/tpl.marko"), require)

Whether this breaks anything else I don't know. If it does I'll have a go at writing a marko loader for webpack, though it wouldn't surprise me if the use of require.resolve instead of a plain require is still a problem

@wheresrhys
Copy link

On investigating, this would involve a change to TypeConverter. Is this something you'd consider?

@patrick-steele-idem
Copy link
Contributor

Hey @wheresrhys, I think the right thing to do here is to use the markoify Browserify transform with Webpack using the transform loader for webpack:
https://github.com/webpack/transform-loader

The markoify transform will auto compile the referenced Marko templates and transform the code to require the generated .marko.js file (e.g. require('./tpl.marko.js'). Have you given that a try?

Unfortunately, generating the following code would not work since the referenced template may not already be compiled:

__loadTemplate(require("../../components/nav/tpl.marko.js"), require)

Marko is designed to generate code that always works on the server. We use require.resolve('./template.marko') instead of require('./template.marko') because the Node.js require extension for Marko is optional. We provide transforms for JavaScript module bundlers so that referenced templates will automatically be compiled and required in. I hope that clarifies.

@patrick-steele-idem
Copy link
Contributor

Hey @wheresrhys, were you able to get things working with with the markoify transform? If you still think it is need to generate compiled code differently such that it doesn't use require.resolve('./foo.marko') and instead uses require('./foo.marko') then it might be reasonable to offer that as a compile-time option:

require('marko/compiler').defaultOptions.useRequireExtension = true;

I'm doing some housecleaning so I am going to go ahead and close this issue, but please feel free to open another Github issue if you would like to pursue the proposed idea or any other ideas. Thanks!

@enyancc
Copy link

enyancc commented Feb 12, 2016

I tried with transform-loader and the markoify. It worked for me, but webpack does not track any changes in templates, so I just wrote no-brainer marko-loader for webpack, which solves this problem.

var marko = require('marko/compiler');

module.exports = function (source) {
  if (this.cacheable) this.cacheable();

  return marko.compile(source, '.', {
    writeToDisk: false
  });
};

@patrick-steele-idem
Copy link
Contributor

@naumovs thanks for sharing. If you are interested in maintaining a loader for others to use I can give you access to github.com/marko-js/marko-loader, or the webpack folks may let you maintain the repo at github.com/webpack/marko-loader. It would be great to have an official webpack loader for those who want to use webpack (even if the code for the loader is trivial). It would be also good to update the marko docs to describe usage with webpack. Please let me know if you are interested in helping out.

@PierBover
Copy link

@sergiirocks I'm using your loader but getting this error when building:

the request of a dependency is an expression

Any idea what might be happening?

Do you have an example on how to use it in webpack.config.js?

@PierBover
Copy link

@patrick-steele-idem I have created this test project.

https://github.com/PierBover/markojs-webpack-test

You just need to npm install and then webpack to reproduce the error.

@patrick-steele-idem
Copy link
Contributor

Marko has been updated to be compatible with wepback. New version published: marko@3.10.1

Also see: https://github.com/marko-js/marko-loader

@PierBover
Copy link

Awesome @patrick-steele-idem !

@PierBover
Copy link

It does work, although I'm still getting Webpack warnings:

WARNING in .//marko/runtime/stream/index-browser.js
Critical dependencies:
6:17-40 the request of a dependency is an expression
10:13-32 the request of a dependency is an expression
@ ./
/marko/runtime/stream/index-browser.js 6:17-40 10:13-32

@patrick-steele-idem
Copy link
Contributor

It does work, although I'm still getting Webpack warnings:

Yes, for now there is no way to remove the warnings without potentially breaking things. In the next version of Marko we can revisit how the optional "streams" module is enabled for the browser.

@MaestroJurko
Copy link

Hi, tried marko-loader - it bundles js but not css. Any suggestions?

 plugins: [
    // Avoid publishing files when compilation failed:
    new webpack.NoEmitOnErrorsPlugin(),
    // Write out CSS bundle to its own file:
    new ExtractTextPlugin('dist/bundle.css', { allChunks: true })
  ]
test: /\.(css|less)$/,
        loader: ExtractTextPlugin.extract({
          fallback: 'style-loader?sourceMap',
          use: 'css-loader?sourceMap!less-loader'
        }),

@ColonelSanderson
Copy link

Hi, tried marko-loader - it bundles js but not css. Any suggestions?

 plugins: [
    // Avoid publishing files when compilation failed:
    new webpack.NoEmitOnErrorsPlugin(),
    // Write out CSS bundle to its own file:
    new ExtractTextPlugin('dist/bundle.css', { allChunks: true })
  ]
test: /\.(css|less)$/,
        loader: ExtractTextPlugin.extract({
          fallback: 'style-loader?sourceMap',
          use: 'css-loader?sourceMap!less-loader'
        }),

I'm also experiencing this.

mlrawlings pushed a commit that referenced this issue Jul 14, 2023
* chore: refactor runtime project structure
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants