Git Product home page Git Product logo

webpack's Introduction


@marko/webpack
API Stability TypeScript Styled with prettier Build status NPM Version Downloads Browser Bundle Size

A Marko plugin and loader for Webpack.

Details

Loader: @marko/webpack/loader

The loader portion of this module can be used standalone and simply transforms your Marko templates into the appropriate JavaScript depending on your webpack target.

You can override the output by adding a target option to the loader of target: "server" | "browser".

Plugin: @marko/webpack/plugin

The plugin actually creates two separate webpack plugins, the browser plugin and the server plugin.

These are intended to be used in a isomorphic webpack multi compiler where you are bundling both the server and the browser. The way it works is that the server plugin is going to analyze the top level Marko components in your server and automatically communicate with the browser compiler to retrieve the assets for that template.

This plugin also analyzes the top level Marko templates and determines if it is possible for them to rerender (currently the heuristic is simply does the component have an associated class or component.js). The plugin will automatically skip sending down any unnecessary top level templates to the browser.

The end result is that you setup a multi compiler (as shown below) and you can simply import Marko templates, and all assets are automatically generated and inlined into an optimized server response. No need to keep track of a webpack manifest yourself!

Tag: <webpack-assets>

The <webpack-assets> tag can be used along with the plugin in a multi-compiler setup. This tag allows you to inject <script>/<style> tags into a server-rendered template for the assets of an entry in the client compiler.

Example Usage

<webpack-assets entry="tracking"/>

Example Config

// ...
export default [
  {
    entry: "./server.js",
    plugins: [markoPlugin.server]
    // ...
  },
  {
    // ...
    entry: {
      tracking: "./tracking.js"
    },
    plugins: [markoPlugin.browser]
  }
];

Installation

@marko/webpack >= 7 Only supports Marko 5+. For Marko 4 support use @marko/webpack@6.

npm install @marko/webpack

Example

import MarkoPlugin from "@marko/webpack/plugin";

const markoPlugin = new MarkoPlugin();

export default [
  {
    entry: "./server.js",
    module: {
      rules: [
        {
          test: /\.marko$/,
          loader: "@marko/webpack/loader"
        }
      ]
    },
    plugins: [markoPlugin.server]
  },
  {
    rules: [
      {
        test: /\.marko$/,
        loader: "@marko/webpack/loader"
      },
      // If using `style` blocks with Marko you must use an appropriate loader
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"]
      }
    ],
    plugins: [markoPlugin.browser]
  }
];

Babel options (Marko 5+)

If you are using Marko 5 with this plugin you can manually override the Babel configuration used by passing a babelConfig object along side the @marko/webpack/loader. By default Babels regular config file resolution will be used.

export default {
    module: {
      rules: [
        {
          test: /\.marko$/,
          loader: "@marko/webpack/loader",
          options: {
            babelConfig: {
              presets: [
                ["@babel/preset-env", { node: "current" }]
              ]
            }
          }
        }
      ]
    }
  },

Multiple client side compilers

Sometimes you need to have multiple compilers for your client side bundles. For example with i18n or even shipping dynamic runtime bundles to the browser.

The Marko webpack browser plugin can be passed to multiple webpack compilers. At runtime you can provide a $global.buildName when rendering which will cause assets from the webpack compiler with that name to be included in the page.

For example with the webpack i18n plugin you might have a config like the following:

import MarkoPlugin from "@marko/webpack/plugin";
import I18nPlugin from "i18n-webpack-plugin";

const languages = {
  en: null,
  de: require("./de.json")
};

const markoPlugin = new MarkoPlugin();

export default [
  {
    name: "Server",
    entry: "./server.js",
    module: {
      rules: [
        {
          test: /\.marko$/,
          loader: "@marko/webpack/loader"
        }
      ]
    },
    plugins: [markoPlugin.server]
  },
  ...Object.keys(languages).map(language => ({
    name: `Browser-${language}`,
    rules: [
      {
        test: /\.marko$/,
        loader: "@marko/webpack/loader"
      },
      // If using `style` blocks with Marko you must use an appropriate loader
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"]
      }
    ],
    plugins: [new I18nPlugin(languages[language]), markoPlugin.browser]
  }))
];

With the above config you can render your top level Marko template server side with a $global.buildName, like so:

template.render({ $global: { buildName: "Browser-de" } });

This will automatically send assets for the German language. Of course in this case you'll want to conditionally send the appropriate assets given a users locale. This can be some simply, like so:

template.render({ $global: { buildName: `Browser-${req.language}` } });

Note: If a bundle with the provided name does not exist an error will be thrown.

Multiple copies of Marko

In some cases you may want to embed multiple isolated copies of Marko on the page. Since Marko relies on some window properties to initialize this can cause issues. For example, by default Marko will read the server rendered hydration code from window.$components. In Marko you can change these window properties by rendering with { $global: { runtimeId: "MY_MARKO_RUNTIME_ID" } } as input on the server side.

This plugin exposes a runtimeId option produces output that automatically sets $global.runtimeId on the server side and initializes properly in the browser. The runtimeId will default to the uniqueName option from the server compiler in the webpack config.

import MarkoPlugin from "@marko/webpack/plugin";

const markoPlugin = new MarkoPlugin({
  runtimeId: "MY_MARKO_RUNTIME_ID" // default to webpack `output.uniqueName` option.
});

Note: This option will also override the default values for the jsonpFunction, chunkCallbackName and hotUpdateFunction webpack output options, which all use global variables, to be prefixed with the runtimeId.

Dynamic public paths

When using the plugin, the server will automatically sync the runtime __webpack_public_path__ with the browser. This means that you only need to setup the dynamic public path on the server side.

Code of Conduct

This project adheres to the eBay Code of Conduct. By participating in this project you agree to abide by its terms.

webpack's People

Contributors

dylanpiercey avatar mlrawlings avatar rturnq avatar taylor-hunt-kr avatar tigt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

webpack's Issues

Breaks if component filename contains `?`

  • @marko/webpack version: 7.0.0-2
  • Environment: Node 14.15.4 on MacOS

I was using a filesystem-based router that supports querystring parameters.

If I had to guess, the ? in the filename conflicts with Webpack’s old-fashioned loader syntax.

Steps to Reproduce

  1. Name a .marko file with ? somewhere in it. I had ?search.marko.

  2. Attempt to bundle it — I was using it as a route entry point, so it was imported from a .js file.

  3. Behold:

    ERROR in ./routes/_router.js 19:0-36
    Module not found: Error: Can't resolve './?search.marko?assets' in '~/repo/routes'
     @ ./index.js 4:0-40 24:11-24
    

And if you think ?param.marko is goofy…

The Marko compiler gets confused if the standard directory/index.ext convention is used, since it supports component-name/index.marko. As a result, this router instead has the convention of directory/.marko.

You might be pleasantly surprised to learn that works.

Customizable asset output

Description

(Old, original issue for historical purposes: #11)

Right now, @marko/webpack writes markoc’s produced component assets to the HTML like so in /src/loader/get-asset-code.ts:

if (assets.js) {
  const nonceAttr = nonce ? ` nonce=${JSON.stringify(nonce)}` : "";
  assets.js.forEach(js => {
    this.write(
      `<script src=${JSON.stringify(__webpack_public_path__+js)}${nonceAttr} async></script>`
    );
  });
}
if (assets.css) {
  assets.css.forEach(css => {
    this.write(
      `<link rel="stylesheet" href=${JSON.stringify(__webpack_public_path__+css)}>`
    );
  });
}

There’s nothing wrong with this, but its one-size-fits-all approach may be unsuitable for a number of reasons…

Why

  • Hooking into the Webpack build process after the compiler-discovered component assets are output
  • Adding application-specific code around <init-components/> and <await-reorderer/> — I personally want to performance.mark() around them.
  • Serving modern vs. transpiled JS via <script type=module> and <script nomodule>
  • More-intelligent bundling of specific scripts based on heuristics/perf monitoring/etc.
  • The nonces aren’t always applicable — if script-src 'self' 'nonce-…', then non-inline scripts don’t need one. (That’s our CSP configuration.)
  • Sub-Resource Integrity
    • Different hash algorithms (currently SHA-256, 384, and 512); potentially dictated by regulation and security standards, so we can’t choose a one-size-fits-all algorithm
    • Multiple hash algorithms in a single integrity attribute, for future-proofing/fallbacks
  • Ordering CSS before JS and vice-versa
  • prefetch, preload, and modulepreload <link>s
  • Non-render-blocking CSS for components later in the page (usually involves <link rel=stylesheet>) midway through the <body>
  • <script defer> instead of <script async> on pages that don’t stream HTML
  • Inlining sufficiently-small scripts and styles
    • The old-fashioned way: <script>…</script> and <style>…</style>
    • A slightly fancier way for more scheduling control: <script defer src="data:application/javascript,…">
  • Loading other assets after @marko/webpack’s asset output, but before </head>
  • crossorigin attribute for preventing double-downloads, fine-tuning HTTP/2 coalescing with different origins
  • media attribute on <link>
  • Bundling component CSS/JS for older HTTP/1.1 connections
  • Deferring all JavaScript to experiment if it’s faster than the current method on certain devices/connections/pages/etc.
  • Lazy-loading stylesheets, async Webpack modules, etc.

Possible Implementation & Open Questions

In the Webpack plugin configuration, an author could pass their own function. Their passed function could be .toString()’d to comply with the reasons get-asset-code.ts mostly just exports a big function that templates JavaScript source code.

Maybe with a signature like this:

interface CustomRenderFunction {
  assets?: array<Asset>;
  nonce?: string;
  runtimeId?: string;
  out: {
    write: function;
    flush: function;
    end: function;
  }
}

interface Asset {
  path: string;
  type: 'css' | 'js';
  // etc…
}

Is this something you're interested in working on?

Yes

Cannot assign to read only property 'exports' of object '#<Object>'

Version: 4.1.1

Details

After updating to the latest version of @marko/webpack, when I load the app in the browser I get the following error message:

Cannot assign to read only property 'exports' of object '#<Object>'

This prevents the rest of the app to work correctly.

When compiling the project, I also get the following warning:

"export 'default' (imported as 'component') was not found in './index.marko'

repeated multiple times (for each component).

I'm not sure if this is the expected behavior for @marko/webpack 4.1.1, if it's a breaking change compared to the way components are written.

Your Environment

  • Chrome (latest)
  • Firefox (latest)
  • nodejs 12
  • MacOS, Linux

Steps to Reproduce

I tried also with the marko-webpack repository from the markojs examples updating all dependencies to the latest available versions, and I get the same error.

https://github.com/MiloCasagrande/marko-webpack/tree/marko-webpack-4.1.1

Automatically include discovered taglibs when compiling

Right now, the Webpack sample ships by externalizing node_modules/ for the server build. But that results in errors like this when using dependency taglibs:

~/git/repo/node_modules/some-folder/components/Button/Button.marko:1
$ const { kind, renderBody, secondary, ...attrs } = input
  ^^^^^

SyntaxError: Unexpected token const

The fix could be dynamically updating externals like the following:

// webpack.config.js
externals: [/^[^./!](?!.*\/node_modules\/some-taglib)/]

Marko stopped working after upgrade to 5.31.16

Marko Version: 5.31.16

Details

[email protected] /Users/xtreme/Documents/GitHub/heretic
├─┬ @marko/[email protected]
│ └── [email protected] deduped
└─┬ [email protected]
└─┬ @marko/[email protected]
└── [email protected] deduped

Expected Behavior

Everything was fine on 5.31.14. I expect the same behaviour on 5.31.16 ;-)

Actual Behavior

There is no re-hydration of server code, and the page is empty. The JS events are not triggered (e.g. onMount)

Possible Fix

Currently the only way for me is to downgrade to 5.31.14.

Additional Info

Your Environment

Mac OS Sonoma, MacBook Pro, 32 GB RAM
Vivaldi 6.2.3105.58

Steps to Reproduce

  1. Clone https://github.com/hereticjsorg/heretic.git
  2. npm i
  3. npm run configure
  4. npm run build -- --dev
  5. npm run server
  6. Go to http://127.0.0.1:3001

Maximum call stack size exceeded when component references itself

Version: @marko/[email protected]

Details

I'm using the webpack-express template from the marko cli tool. I have a component named comment-box which references itself for child comments. When I run the project's npm run dev (webpack serve), an error is thrown and all CSS stops being served to the browser.

Expected Behavior

To include itself as child components.

Actual Behavior

An error is thrown in console and no CSS is served to the browser.

Possible Fix

Unknown

Your Environment

Debian 10, NPM 6.14.15, Node v14.17.6,

Steps to Reproduce

Component template components/comment-box/index.marko

<div class="comment-box flex">
  <div class="comment-minimize flex-grow-0">
    <i class="fas fa-minus-square comment-icon"></i><br/>
    ▲<br>
    ▼
  </div>
  <div>
    <div class="comment-header">
      ${comment.user.username} ${comment.score} points ${comment.age}
    </div>
    <p class="comment-text">
    ${comment.text_raw}
    </p>
    <div class="comment-footer">
      reply
    </div>
  </div>
  <div class="comment-replies">
    <if(typeof comment.comments !== "undefined")>
      <for|comment| of=comment.comments>
        <comment-box comment=comment /> <!-- this is causing the error -->
      </for>
    </if>
  </div>
</div>

Stack Trace

ERROR in ./src/pages/submission/template.marko?browser-entry
  Module build failed (from ./node_modules/@marko/webpack/dist/loader/index.js):
  RangeError: /home/aerlin/projects/markotest/src/pages/submission/template.marko: Maximum call stack size exceeded
      at NodePath._containerInsert (/home/aerlin/projects/markotest/node_modules/@babel/traverse/lib/path/modification.js:51:26)
      at NodePath._containerInsertAfter (/home/aerlin/projects/markotest/node_modules/@babel/traverse/lib/path/modification.js:85:15)
      at NodePath.insertAfter (/home/aerlin/projects/markotest/node_modules/@babel/traverse/lib/path/modification.js:129:17)
      at NodePath.replaceWithMultiple (/home/aerlin/projects/markotest/node_modules/@babel/traverse/lib/path/replacement.js:36:22)
      at NodePath.pushContainer (/home/aerlin/projects/markotest/node_modules/@babel/traverse/lib/path/modification.js:215:15)
      at addBrowserDeps (/home/aerlin/projects/markotest/node_modules/@marko/translator-default/dist/util/add-dependencies.js:150:15)
      at addHydrateDeps (/home/aerlin/projects/markotest/node_modules/@marko/translator-default/dist/util/add-dependencies.js:77:5)
      at addHydrateDeps (/home/aerlin/projects/markotest/node_modules/@marko/translator-default/dist/util/add-dependencies.js:87:9)
      at addHydrateDeps (/home/aerlin/projects/markotest/node_modules/@marko/translator-default/dist/util/add-dependencies.js:87:9)
      at addHydrateDeps (/home/aerlin/projects/markotest/node_modules/@marko/translator-default/dist/util/add-dependencies.js:87:9)

  browser:modern (webpack 5.51.1) compiled with 1 error in 1570 ms

Loader support for split component lazy hydration

Description

As part of the lazy hydration PR in marko/next, we need the loader to handle loading multiple possible instances of marko runtime. (prob not describing this perfectly).

Why

Possible Implementation & Open Questions

In the working version on my local, I believe you added to loader/get-asset-code.js a Set to handle this in the code gen:
const writtenAssets = this.global.___written || (this.global.___written = new Set());

Additionally we used the following webpack config:

const path = require("path");
const webpack = require("webpack");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MarkoPlugin = require("@marko/webpack/plugin").default;
const CSSExtractPlugin = require("mini-css-extract-plugin");
const SpawnServerPlugin = require("spawn-server-webpack-plugin");
const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");

const { NODE_ENV } = process.env;
const isProd = NODE_ENV === "production";
const isDev = !isProd;
const markoPlugin = new MarkoPlugin();
const spawnedServer = isDev && new SpawnServerPlugin();

module.exports = [
  compiler({
    name: "Client",
    optimization: {
      runtimeChunk: "single",
      splitChunks: {
        chunks: "all",
        cacheGroups: {
          vendors: {
            test: /\/(node_modules|marko)\//,
            name: "vendors"
          }
        }
      }
    },
    output: {
      filename: "[name].[contenthash:8].js",
      path: path.join(__dirname, "dist/client")
    },
    devServer: isDev ? {
      overlay: true,
      stats: "minimal",
      contentBase: false,
      ...spawnedServer.devServerConfig
    }: undefined,
    plugins: [
      new webpack.DefinePlugin({
        "process.browser": true
      }),
      new CSSExtractPlugin({
        filename: "[name].[contenthash:8].css"
      }),
      isProd && new OptimizeCssAssetsPlugin(),
      markoPlugin.browser
    ]
  }),
  compiler({
    name: "Server",
    target: "async-node",
    externals: [/^[^./!]/], // excludes node_modules
    optimization: {
      minimize: false
    },
    output: {
      libraryTarget: "commonjs2",
      path: path.join(__dirname, "dist/server")
    },
    plugins: [
      new webpack.DefinePlugin({
        "process.browser": undefined,
        "process.env.BUNDLE": true
      }),
      new webpack.BannerPlugin({
        banner: 'require("source-map-support").install();',
        raw: true
      }),
      new CSSExtractPlugin({
        filename: "[name].[contenthash:8].css"
      }),
      isDev && spawnedServer,
      markoPlugin.server
    ]
  })
];

// Shared config for both server and client compilers.
function compiler(config) {
  return {
    ...config,
    mode: isProd ? "production" : "development",
    devtool: isProd ? "source-map" : "inline-source-map",
    output: {
      publicPath: "/static/",
      ...config.output
    },
    resolve: {
      extensions: [".js", ".json", ".marko"],
      symlinks: false,
      alias: {
        marko: require("path").dirname(require.resolve("marko/package.json"))
      }
    },
    module: {
      rules: [
        {
          test: /\.marko$/,
          loader: "@marko/webpack/loader"
        },
        {
          test: /\.(less|css)$/,
          use: [CSSExtractPlugin.loader, "css-loader", "less-loader"]
        },
        {
          test: /\.svg/,
          loader: "svg-url-loader"
        },
        {
          test: /\.(jpg|jpeg|gif|png)$/,
          loader: "file-loader",
          options: {
            // File assets from server & browser compiler output to client folder.
            outputPath: "../client"
          }
        }
      ]
    },
    plugins: [...config.plugins, isProd && new CleanWebpackPlugin()].filter(Boolean)
  };
}

Is this something you're interested in working on?

Asset loading strategy problems

  1. Injecting assets before the <!doctype> puts the page in Quirks Mode; that’s clearly bad and the team has acknowledged that, so I won’t waste more words on it. Some other possible problems depending on injection point:

    • Should be after <meta charset>
    • Should be after <base>
    • Should be after <meta name="referrer-policy">
    • Should be after any <meta http-equiv="Content-Security-Policy>
    • …probably other stuff, including things to come in the future. Maybe a heuristic of “before the first <link>/<script> element we see”, or an explicit marker string in the <head> to .replace()?
  2. Resource loading order is nondeterministic: <link rel=preload> is higher-priority than <link rel=stylesheet>, but since <link rel=preload> is injected via script, there are race conditions involving:

    • If the <script> executes before the lookahead preparser finds the <link>s
    • Across different browser (& version) JS schedulers, network heuristics, and HTTP/2 prioritization
    • How much of the HTML is received across IP/TCP/etc. network byte boundaries
  3. The resource-loading strategy has a lot of thought put into it, but it may not fit all. Some things I wanted to try:

@marko/webpack is trying to require the package "tslib" without it being listed in its dependencies

  • @marko/webpack version: 1.2.5
  • Environment: Node.js 12.13.0
  • Operating System: MacOS 10.14.6

I tried Yarn’s Plug ‘n Play for faster CI installs, and its increased strictness found what looks like an implicit dependency.

Specifically, the distributed version of @marko/webpack version 1.2.5 will require("tslib") in its compiled code:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");

…but tslib is not listed as a dependency.

Possible Fix

npm i tslib

Steps to Reproduce

  1. Add "installOptions": { "pnp": true } to the package.json
  2. yarn
    yarn run webpack # you need a webpack config; the example repo will do fine

Stack Trace

$ webpack
~/Library/Caches/Yarn/v6/npm-webpack-cli-3.3.10-17b279267e9b4fb549023fae170da8e6e766da13-integrity/node_modules/webpack-cli/bin/cli.js:93
                                throw err;
                                ^

Error: Package "@marko/[email protected]" (via "~/Library/Caches/Yarn/v6/npm-@marko-webpack-1.2.5-494756a2195d8020c8885c571b2af75e68eacbd7-integrity/node_modules/@marko/webpack/dist/plugin/index.js") is trying to require the package "tslib" (via "tslib") without it being listed in its dependencies (marko, webpack, base-x, lasso-modules-client, loader-utils, sort-keys, webpack-virtual-modules, @marko/webpack)
  code: 'UNDECLARED_DEPENDENCY',
  data: {
    request: 'tslib',
    issuer: '~/Library/Caches/Yarn/v6/npm-@marko-webpack-1.2.5-494756a2195d8020c8885c571b2af75e68eacbd7-integrity/node_modules/@marko/webpack/dist/plugin/index.js',
    issuerLocator: { name: '@marko/webpack', reference: '1.2.5' },
    dependencyName: 'tslib',
    candidates: [
      'marko',
      'webpack',
      'base-x',
      'lasso-modules-client',
      'loader-utils',
      'sort-keys',
      'webpack-virtual-modules',
      '@marko/webpack'
    ]
  }
}

Incompatible with Webpack 5

Version: 6.2.9

Details

Webpack 5 recently released, and @DylanPiercey asked if I had run into any compat issues when trying to upgrade.

Answer: yes.

Expected Behavior

A successful Webpack 4 config without deprecation warnings should successfully complete a build after upgrading to "webpack": "^5".

Actual Behavior

Errors are thrown and a deprecation message is shown.

Your Environment

  • Environment name and version (e.g. Chrome 39, node.js 5.4): Node.js v14.6.0
  • Operating System and version (desktop or mobile): MacOS

Steps to Reproduce

  1. Check out the @marko/webpack sample repo
  2. Change the "webpack" version in its package.json to "^5"
  3. Run the build

Stack Trace

~/repo/node_modules/webpack-virtual-modules/index.js:84
  if (storage.data instanceof Map) {
              ^

TypeError: Cannot read property 'data' of undefined
    at setData (~/repo/node_modules/webpack-virtual-modules/index.js:84:15)
    at CachedInputFileSystem.finalInputFileSystem._writeVirtualFile (~/repo/node_modules/webpack-virtual-modules/index.js:118:9)
    at VirtualModulesPlugin.writeModule (~/repo/node_modules/webpack-virtual-modules/index.js:64:24)
    at ~/repo/node_modules/webpack-virtual-modules/index.js:165:14
    at Array.forEach (<anonymous>)
    at afterResolversHook (~/repo/node_modules/webpack-virtual-modules/index.js:164:40)
    at Hook.eval [as call] (eval at create (~/repo/node_modules/tapable/lib/HookCodeFactory.js:19:10), <anonymous>:7:1)
    at Hook.CALL_DELEGATE [as _call] (~/repo/node_modules/tapable/lib/Hook.js:14:14)
    at WebpackOptionsApply.process (~/repo/node_modules/webpack/lib/WebpackOptionsApply.js:555:33)
    at createCompiler (~/repo/node_modules/webpack/lib/webpack.js:78:28)

yarn why confirms the bad version of webpack-virtual-modules is imported by @marko/webpack.

Forcibly upgrading webpack-virtual-modules to 0.3.1 via resolutions fixes the above error, but produces a new one:

TypeError: desc.import is not iterable
    at ~/repo/node_modules/webpack/lib/DynamicEntryPlugin.js:56:33
    at processTicksAndRejections (internal/process/task_queues.js:93:5)

Also, it produces this trace for a deprecation:

(node:28127) [DEP_WEBPACK_COMPILATION_NORMAL_MODULE_LOADER_HOOK] DeprecationWarning: Compilation.hooks.normalModuleLoader was moved to NormalModule.getCompilationHooks(compilation).loader
    at getNormalModuleLoader (~/repo/node_modules/webpack/lib/Compilation.js:295:39)
    at Object.get normalModuleLoader [as normalModuleLoader] (~/repo/node_modules/webpack/lib/Compilation.js:601:12)
    at ~/repo/node_modules/@marko/webpack/dist/plugin/index.js:58:35
    at Hook.eval [as call] (eval at create (~/repo/node_modules/tapable/lib/HookCodeFactory.js:19:10), <anonymous>:9:1)
    at Hook.CALL_DELEGATE [as _call] (~/repo/node_modules/tapable/lib/Hook.js:14:14)
    at Compiler.newCompilation (~/repo/node_modules/webpack/lib/Compiler.js:915:30)
    at ~/repo/node_modules/webpack/lib/Compiler.js:957:29
    at Hook.eval [as callAsync] (eval at create (~/repo/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (~/repo/node_modules/tapable/lib/Hook.js:18:14)
    at Compiler.compile (~/repo/node_modules/webpack/lib/Compiler.js:952:28)

Cache Marko Files

Description

As per a comment by @DylanPiercey on gitter

Marko files are marked as non cachable in webpack because we don’t currently have a good way to tell webpack all of the folders and files that, although unreferenced in the compiled code, can cause the compilation to change.

So basically, I think it would be very valuable if marko files were cached during builds.

Why

I have been attempting to migrate my company's large-ish project from lasso to webpack. The last hurdle appears to be supporting a fast development environment. Though I'm not entirely sure if caching is the sole reason for this, every rebuild while using webpack's watch mode causes all the marko files, and only the marko files, across the app to be rebuilt even if they haven't changed. We have quite a few marko components so this ends up taking a while.

Possible Implementation & Open Questions

I had some small results by using cache-loader to cache the results of the marko-loader, however when running webpack in build mode, modifications wouldn't show up. And although this was faster, I wouldn't necessarily call it fast. It may be worth looking into how the cache-loader operates if there isn't already an idea on where to begin with this.

Is this something you're interested in working on?

In the interest of getting my team's project on to webpack faster I'd be willing to provide as much support for this issue as possible, though I'm not all that knowledgeable about Marko internals or webpack loaders.

I've also been documenting the migration process and would be willing to contribute to a lasso to webpack migration guide.

Add CSP nonce to the rendered script

Version: 2.0.0

Description

When using CSP headers with a CSP nonce value, markojs itself correctly sets the nonce attribute of the script tag for the various resources.

The issue is with the dynamically loaded script from marko/webpack that does not contain the nonce attribute, and the browser will not execute it.

Why

We rely on CSP headers in our webapps, but we have to fallback to unsafe-inline in order to correctly use marko/webpack.

Possible Implementation & Open Questions

webpack has a "feature" where setting the variable __webpack_nonce__ in the JS entry point, it will add the nonce attribute to the scripts, not sure if that's something that can be leveraged here.

It would be great to have a more detailed approach on how the CSP headers are set as well, with maybe the possibility to compute the sha of the code instead on relying on the nonce value.

Is this something you're interested in working on?

Maybe, with guidance.

Compilation errors starting with 8.0.1

Versions:

node 14.16.0
@marko/webpack version: 8.0.1
less-version: 4.1.1 (Published 2 months ago)
less-loader-version: 8.1.0 (Published 4 days ago)

Details

Marko style blocks break with and without preprocessor (less). Separate style.css/style.less gets included.
The following are two errors emitted during webpack compilation of the browser config:


Component Errors

The following component is a single file component, has a style.less and a class block.

ERROR in ./src/components/material-icon/material-icon.marko 6:0-161
Module not found: Error: Can't resolve '..\..\..\node_modules\@marko\webpack\dist\loader\index.js' in 'D:\PROJECT\src\components\material-icon' 

Entrypoint Errors

The following Entrypoint only has a style.less block apart from the "html" part

ERROR in ./src/error.marko?browser-entry 11:0-109
Module not found: Error: Can't resolve './index.marko?virtual=./index.marko.less' in 'D:\PROJECT\src'

Expected Behavior

In @marko/webpack version 7.1.4 "everything works™".
Less gets compiled to CSS and output properly, components get properly loaded and overall javascript works.

Actual Behavior

Starting version 8.0.x the style blocks arent included in the output. This also breaks the javascript as a module is missing.
Entrypoints with just html/js work, but including even a single style block - not even less and even on components - break browser js (see error below).
CSS only works on subcomponents where it's split to a separate file.

Uncaught Error: Cannot find module './index.page.marko.less!=!..\..\node_modules\@marko\webpack\dist\loader\index.js!./index.page.marko?virtual=./index.page.marko.less'

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on Greenkeeper branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please click the 'fix repo' button on account.greenkeeper.io.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.