Code Monkey home page Code Monkey logo

webpack-chain's People

Contributors

aretecode avatar beeequeue avatar bolasblack avatar braincrumbz avatar cyjake avatar dsanders11 avatar edmorley avatar eliperelman avatar fimars avatar githoniel avatar huang-x-h avatar imyelo avatar jetsly avatar joeldenning avatar loveky avatar mc-zone avatar nashaofu avatar nickolas1 avatar opl- avatar renovate-bot avatar renovate[bot] avatar simon04 avatar sirlancelot avatar tauren avatar ulivz avatar walkerburgin avatar xbigcat avatar xiaoxiaojx avatar yordis avatar yyx990803 avatar

Stargazers

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

Watchers

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

webpack-chain's Issues

docs with config snippets for webpack

It would be great if examples in the documentation would include minimal webpack's configs or config snippets that correspond to the examples. Perhaps, that would help to better understand the API.

immutable API

It would be great to be able to create modules like:

// Require the webpack-chain module. This module exports a single
// constructor function for creating a configuration API.
const config = require('webpack-chain/immutable');

// No need to instantiate, because config is already a root empty value.
// const config = new Config();

// Make configuration changes using the chain API.
// Every API call tracks a change to the stored configuration.

// Interact with entry points
const init = config
  .entry('index')
    .add('src/index.js')
    .end()
  // Modify output settings
  .output
    .path('dist')
    .filename('[name].bundle.js');

// Create named rules which can be modified later
const eslint = init.module
  .rule('lint')
    .test(/\.js$/)
    .pre()
    .include('src')
    // Even create named loaders for later modification
    .loader('eslint', 'eslint-loader', {
      rules: {
        semi: 'off'
      }
    });

const babel = eslint.module
  .rule('compile')
    .test(/\.js$/)
    .include('src', 'test')
    .loader('babel', 'babel-loader', {
      presets: [
        [require.resolve('babel-preset-es2015'), { modules: false }]
      ]
    });

// Create named plugins, too!

const plugins = babel
  .plugin('clean')
  .use(CleanPlugin, [BUILD], { root: CWD });

// Export the completed configuration object to be consumed by webpack
module.exports = babel.getConfig();

module.rule(...).loader(...).use is not a function

I'm considering using Neutrino (which uses this package) and I'm trying to add ExtractTextPlugin (https://github.com/webpack-contrib/extract-text-webpack-plugin) to my Neutrino project.

The extract-text-webpack-plugin docs use this example:

const ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader"
        })
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin("styles.css"),
  ]
}

So, I assumed this would be the equivalent for webpack-chain (this is a custom preset being called in my package.json):

const ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = ({ config }) => {
  config.module
    .rule("css")
    .use(ExtractTextPlugin.extract, {
      fallback: "style-loader",
      use: "css-loader"
    });
  config.plugin("extract-css").use(ExtractTextPlugin, "styles.css");
};

But I get the following error:

config.module.rule(...).loader(...).use is not a function

Am I doing anything wrong here?

Prepending oneOf rules

Hello! I'm working with a vue project. It has a default set of loaders for various file types.
For scss it uses oneOf ruleset with resourceQuery's, the last of them is what I believe a default rule with no resourceQuery (correct me if I'm wrong here).

My task required to extract raw css as a string and the issue here is that the final default loader in vue is vue-style-loader which does not allow this. I decided to use css-loader for this.

So the question is: am I able to put my own oneOf rule before the default one without having to rewrite defaults?

I'm aware I can override loaders in import statement, but I may require to do this in other parts of the project so I thought it would be the best solution.

How to prepend rule loaders?

Loaders on rules are order dependent, yet, looking at the source code for webpack-chain, it's being treated as a map (rule.uses). How would you inject a loader at the head of the loader chain? Right now, i have to clear the uses but that feels like it defeats what webpack-chain is trying for.

//base.js

config.module
	.rule('Javascript')
		.test(/\.jsx?$/)
		.enforce('pre')
		.include
			.add(path.resolve(__dirname, 'src'))
			.end()
		.use('babel')
			.loader('babel-loader');

//development.js

config.module
	.rule('Javascript').uses.clear().end()
	.use('hot')
		.loader('react-hot-loader/webpack').end()
	.use('babel')
		.loader('babel-loader');

Rule paths are difficult to modify

Interacting with the include and exclude APIs for Rule are not friendly, as they only allow adding paths to the Set. Any other operations require using the backing store at _include and _exclude. We should make these work similar to a ChainedSet, but this will mean another breaking change.

Eject config?

This is a Feature Request.

I wonder if you're interested in implementing the eject webpack config feature (similar to what create-react-app does):

config.entry('client').add('src/index.js')

config.plugin('define')
  .use(webpack.DefinePlugin, [{foo: 'foo'}])
  .outputName('webpack.DefinePlugin')

config.toString() // or maybe config.toConfig({ string: true })
//=> '{"entry":{"client":["src/index.js"]},"plugins":[new webpack.DefinePlugin({\"foo\": \"foo\"})]}'

Alternative to `test()` metod

test() method defines expressions tested over files . In webpack-chain this method can be only overridden but can't be extended if its value is an array.

What if we add an alternative method that will be dedicated exactly to extensions and will support ChainedSet interface? Example

config.module
    .rule('scripts')
        .extensions
            .add('js')
            .add('jsx')
            .merge([...])
            .end()
        .use('babel')
            .loader('babel-loader');

This collection can be converted to RegExp just before it is formatted for Webpack compilation.

Pros:

  1. Better API to write middlewares
  2. Extensions of any rule can be extracted and used for other purposes. May be very useful when call linter tools in CLI with the same extensions as a target.

I would even suggest to completely replace test() method as it will simplify the implementation.

Unable to send additional args to 'clean-webpack-plugin'

In my vue.config.js file, I have the following:

..
chainWebpack: config => {
    config
            .plugin('clean')
            .use('clean-webpack-plugin', [
                'css',
                'fonts',
                'images',
                'img',
                'js',
            ], { beforeEmit: true, root: path.join(__dirname, 'public') });
}
..

However, the additional arguments after the array of paths is not being picked up by webpackChain, you can see that from this inspect:

09:51 $ vue inspect --plugin clean
/* config.plugin('clean') */
new (require('clean-webpack-plugin'))(
  'css',
  'fonts',
  'images',
  'img',
  'js'
)

Is there something I'm missing so that the additional args get picked up?

Hard to manage order of ChainedMap

webpack-chain is awesome.

However, it's hard to manage the order of ChainedMap, and order is matter in webpack, e.g., entry/plugins/module.rules.

Is it possible to provide .before() .after() API for every ChainedMap, same as config.plugins.

I suggest to provide the following API:

// same as config.plugin(name).after(otherName)
.before()
.after()

// or maybe
.append()
.prepend()

// sometime will be better then .get(key)
.first()
.last()
.key()

// then we can do this:
const key = config.entryPoints.first().key();
config.entry('abc').before(key).add('abc.js')

Add "serve" method to Config to support "webpack-serve"

webpack-serve is a webpack-dev-server alternative that targets modern browsers.

The configuration is slightly different, as it delegates most options to webpack-dev-middleware and webpack-hot-client through the dev and hot options respectively.

It expects options to be provided through the serve key in the Webpack config, but right now webpack-chain does not let that option go through, which would be convenient even if you decide not to create shorthands for the different parts of it.

Doc: getConfig -> toConfig

The documentation says there is config.getConfig() method to convert the config object to webpack specific configuration, but there is no such method. It should to be changed to .toConfig()

ts-loader not work??

ERROR in ./src/index.ts 33:20
Module parse failed: Unexpected token (33:20)
You may need an appropriate loader to handle this file type.
| 		apiKey: config.EngineApiKey,
| 	},
> 	formatError: (error: any) => {
| 		console.log(error);
| 		return error;
 @ multi ./src/index.ts index[0]

myconfig

const Config = require('webpack-chain');
const path = require('path');

const config = new Config();

config
	.entry('index')
	.add(path.resolve(__dirname, '../src/index.ts'))
	.end()
	.output.path(path.resolve(__dirname, '../dist'))
	.filename('[name].bundle.js');

config.mode('development');
// tslint-loader
config.module
	.rule('lint')
	.test(/\.ts$/)
	.pre()
	.include.add('../src')
	.end()
	.use('tslint')
	.loader('tslint-loader')
	.options({
		rules: {
			fix: true,
			configFile: '../tslint.json',
		},
	});

config.module
	.rule('ts')
	.test(/\.ts$/)
	.include.add('src')
	.end()
	.use('ts-loader')
	.loader('ts-loader');

config.resolve.extensions
	.add('.ts')
	.add('.js')
	.clear();

module.exports = config.toConfig();

I don't know what's wrong with me. It seems that he doesn't carry out ts-loader.

my package.json

"devDependencies": {
    "@2fd/graphdoc": "^2.4.0",
    "@types/bcryptjs": "^2.4.1",
    "@types/bunyan": "^1.8.4",
    "@types/graphql": "^14.0.0",
    "@types/ioredis": "^4.0.1",
    "@types/jsonwebtoken": "^7.2.8",
    "@types/koa": "^2.0.46",
    "@types/koa-router": "^7.0.31",
    "@types/lodash": "^4.14.116",
    "@types/node": "^10.10.1",
    "@types/nodemailer": "^4.6.5",
    "@types/nodemailer-smtp-transport": "^2.7.4",
    "@types/pg": "^7.4.10",
    "@types/uuid": "^3.4.4",
    "@types/validator": "^9.4.2",
    "cross-env": "^5.2.0",
    "nodemon": "^1.18.4",
    "pre-commit": "^1.2.2",
    "prettier": "^1.14.2",
    "tslint": "^5.11.0",
    "tslint-loader": "^3.6.0",
    "typescript": "^3.0.3",
    "webpack": "^4.19.1",
    "webpack-chain": "^4.11.0",
    "webpack-cli": "^3.1.0"
  },
  "dependencies": {
    "apollo-server-koa": "^2.0.7",
    "bcryptjs": "^2.4.3",
    "bunyan": "^1.8.12",
    "dataloader": "^1.4.0",
    "graphql": "^14.0.2",
    "graphql-import": "^0.7.1",
    "ioredis": "^4.0.0",
    "jsonwebtoken": "^8.3.0",
    "koa": "^2.5.3",
    "koa-bunyan-logger": "^2.0.0",
    "koa-router": "^7.4.0",
    "lodash": "^4.17.11",
    "moment": "^2.22.2",
    "nodemailer": "^4.6.8",
    "nodemailer-smtp-transport": "^2.7.4",
    "on-finished": "^2.3.0",
    "pg": "^7.4.3",
    "ts-loader": "^5.1.1",
    "tslib": "^1.9.3",
    "uuid": "^3.3.2",
    "validator": "^10.7.1"
  }

How can I prepend a loader in `.use()` ?

Hi,

I try to integrate webpack-chain in my project but it seems I can't do something.

Let's say I have a TypeScript loader :

chain.module.rule('ts')
    .test(/\.tsx?$/)
    .exclude.add(/(node_modules|bower_components)/).end()
    .use("ts").loader("ts-loader").options(typeScriptConfigurator())

The thing is, now I wish to use React Hot Loader which requires me to add a loader before the "ts-loader" (Because it has to be executed after ts-loader)

Is there some way to do something like ?

chain.module.rule('ts').prependUse("hot").loader("react-hot-loader/webpack")

Thanks in advance.

How to configure multiple pages?

config .entry('index') .add({ pageOne: './src/pageOne/index.js', pageTwo: './src/pageTwo/index.js', pageThree: './src/pageThree/index.js' }) .end()
This is error

Remove rule.

I must be missing something, but how do you remove a rule from existing config?

ExtractTextPlugin Module

First off, loving webpack-chain. Declaratively setting up a webpack config is fantastic.

I'm struggling to switch over ExtractTextPlugin. The pattern I'm looking to convert is well described in the Webpack Migration Guide, specifically the module part:
https://webpack.js.org/guides/migrating/#extracttextplugin-extract

Would you happen to have any suggestions? I'm posting this here in hopes that other people might find this useful.

How do you specify resolveLoader.alias?

According to the webpack resolve docs, you can use alias under resolveLoader and other features familiar from resolve.

I'm using it through a new Vue CLI 3 project, and trying to do the following:
config.resolveLoader.alias.set('text', 'raw-loader'), however config.resolveLoader.alias doesn't exist and isn't in the webpack-chain docs.

With webpack-chain is this impossible?

Human readable output

I tried out the api and tried to create a minimal configuration with only entrypoint ,outputPath and outputFilename.
I get output something like
{"output":{"path":"dist","filename":"bundle.js"},"resolve":{"modules":[],"extensions":[]},"resolveLoader":{"modules":[]},"plugins":[],"entry":{"index":['index.js']}}

Wouldn't it be better to prune out the empty configs of resolve, resolveLoader and plugins?

clarify plugin docs

i wanted to add webpack-manifest-plugin and was only able to do so via trial and error by adding an empty array as the second arg.

What does this arg do? How can I help to improve the docs?

    neutrino.config.plugin('manifest')
      .use(ManifestPlugin, [], { filename: 'manifest.json' });

Move to mozilla-neutrino org?

I placed this repo here because it seemed generic enough, but maybe it should be a part of the Neutrino org just for clarity.

Allow resolve plugin merge

Merge of plugins under a config map has special logic to merge each plugin entry. The same logic should be provided when merging a resolve map, as these can also have plugins.

I am trying to merge the following plugin in a fork of create-react-app / react-scripts that uses neutrino:

 resolve: {
            plugin: {
                // Prevents users from importing files from outside of src/ (or node_modules/).
                // This often causes confusion because we only process files within src/ with babel.
                // To fix this, we prevent you from importing files out of src/ -- if you'd like to,
                // please link the files into your node_modules/ and let module-resolution kick in.
                // Make sure your source files are compiled, as they will not be processed in any way.
                "ModuleScope": {
                    plugin: ModuleScopePlugin,
                    args: [paths.appSrc, [paths.appPackageJson]]
                }
            },

I attach pull request #82 to resolve this issue

Make Plugin API consistent with Loader API

When creating a loader through the Loader API, the signature is:

.loader(name, loader, options)

When modifying a loader it is:

// props: Object: { loader, options }
.loader(name, props => props)

Plugins are different. To instantiate:

.plugin(name).use(plugin, ...args)

To modify requires instantiating the plugin manually through a handler:

.plugin(name).inject((Plugin, args) => new Plugin(...args))

Plugin should hypothetically operate like Loader:

// create
.plugin(name, plugin, ...args)

// modify
.plugin(name, props => props)

Concretely, this could be:

config.plugin('env', EnvironmentPlugin, ['NODE_ENV'])

// ...

config.plugin('env', props => merge(props, { args: [...props.args, 'OTHER_ENV_VAR'] }))

Provide recipes for converting from common babel/eslint/webpack configurations

It would be nice to see documentation that provides example .babelrc, .eslintrc, and webpack.config.js configurations and illustrates how they would be replicated using webpack-chain.

Note that I'm using webpack-chain via neutrino, so I'd also like to make sure I don't blow away settings that were already provided via neutrino presets.

Merging rule loader overwrites existing

"module": {
        "rule": {
          "css": {
            "loader": {
              "css": {
                "options": {
                  "modules": true
                }
              }
            }
          }
        }
      }
    }

This should extend the rule.css.loader.css if one exists, but currently it overwrites.

Support ExtractTextWebpackPlugin

This plugin has two interconnected config entries. A standard plugin, and a special module loader:

{
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader"
        }),
      },
    ],
  },
}

Behind the scenes, this extract function returns an array of loaders, specially formatted like so:

use: [
  { loader: 'extract-text-webpack-plugin/loader', options: { omit: 1, remove: true } },
  { loader: 'style-loader' },
  { loader: 'css-loader' },
]

Not sure why they don't document this api for loader syntax consistency. In any case, ExtractTextPlugin.extract doesn't work well with how webpack-chain currently abstracts loaders in Rule and ChainedMap.

I'm not convinced that webpack-chain's design should accommodate this pattern. Instead I'd suggest testing and documenting how to make it work with .merge() like so:

config.module.rule('style')
  .test(/\.css$/)
  .merge({
    use: ExtractTextPlugin.extract({
      fallback: 'style-loader',
      use: 'css-loader',
    }),
  })

I haven't had time to verify this but I imagine this should work, even though the uses get their names from array indices: '0', '1', '2'.

Does this make sense. Where could this be documented?

how to use a anonymous plugin for create by myself

config.plugin('then')
            .use({
                apply: (compiler) => {
                    compiler.hooks.afterEmit.tap('AfterEmitPlugin', (compilation) => {
                        console.log('worked!')
                    })
                }
            })

the error

TypeError: Cannot read property '__expression' of undefined

but webpack4 support to create anonymous plugin,and in webpack plugins config array,it works fine,how to run in chain?

Improve error message when using .tap() on undefined plugin

STR:

  1. yarn add [email protected] @neutrinojs/[email protected]
  2. mkdir src
  3. touch contribute.json src/index.js
  4. Create a .neutrinorc.js containing:
module.exports = {
  use: [
    '@neutrinojs/web',
    (neutrino) => {
      neutrino.config
        .plugin('copy')
        .tap(args => {
          args[0] = [
            'contribute.json'
          ];
          return args;
        });
    }
  ]
}
  1. yarn start

Expected:
Error message that makes the mistake clear. eg:
Error: Plugin 'copy' is not defined
(along with a stack trace that points to the correct line in .neutrinorc.js)

Actual:
webpack-chain gives an error message that is hard to track back to a root cause (unclear error message and does not reference a specific line in .neutrinorc.js):

C:\Users\Ed\src\neutrino-test\node_modules\webpack-chain\src\Plugin.js:9
    this.init((Plugin, args = []) => new Plugin(...args));
                                     ^

TypeError: Plugin is not a constructor
    at init (C:\Users\Ed\src\neutrino-test\node_modules\webpack-chain\src\Plugin.js:9:38)
    at Object.toConfig (C:\Users\Ed\src\neutrino-test\node_modules\webpack-chain\src\Plugin.js:38:12)
    at clean.Object.assign.plugins.plugins.values.map.plugin (C:\Users\Ed\src\neutrino-test\node_modules\webpack-chain\src\Config.js:69:59)
    at Array.map (<anonymous>)
    at module.exports.toConfig (C:\Users\Ed\src\neutrino-test\node_modules\webpack-chain\src\Config.js:69:38)
    at ChainAction.Future.chain.chain.chain [as mapper] (C:\Users\Ed\src\neutrino-test\node_modules\neutrino\src\api.js:281:61)
    at ChainAction$resolved [as resolved] (C:\Users\Ed\src\neutrino-test\node_modules\fluture\index.js:805:27)
    at resolved (C:\Users\Ed\src\neutrino-test\node_modules\fluture\index.js:220:19)
    at Immediate.EncaseP2$res [as _onImmediate] (C:\Users\Ed\src\neutrino-test\node_modules\fluture\index.js:1847:7)
    at runCallback (timers.js:791:20)
    at tryOnImmediate (timers.js:751:5)
    at processImmediate [as _immediateCallback] (timers.js:722:5)

The root cause here is that the copy plugin is only defined when command === 'build', and so there is no such plugin to .tap() during yarn start.

Add type definition file

I'm using this with Visual Studio Code and it would be great to explore the available API operations via the autocomplete of the editor. If there's a .d.ts file in the npm package, most editors should be able to enable this.

ChainedMap and ChainedSet as a separate package

Hello everyone!

I really love how easy it is to manipulate Webpack configs with webpack-chain. This is possible thanks to ChainedMap and ChainedSet. I wanted to apply the same primitives to other configs such as a PostCSS preset and Jest. Though, it felt kind of strange to use webpack-chain/lib/ChainedMap and webpack-chain/lib/ChainedSet under the hood.

At MOXY, we have created chained-config which is just that:

chained-config offers those constructors in a separate package so that we can apply the same concepts to other configurations other than Webpack.

I'm writing this because I'm obliged by the license to inform you of any changes that I make in your software. But that was not the primary goal. Down the road, we plan to create jest-chain, babel-chain and friends with chained-config. It would be great if webpack-chain could use the same base package. The reason is that chained-config has a some differences that are noted on each API section.

I'm writing this so that the creators of the package may evaluate chained-config and possibly decide if it may be used as the foundation for webpack-chain. I know that this will translate into breaking changes, therefore it must be done at the right time.

Feel free to close this issue if this is something that you do not want to do.

Thanks for this awesome package!

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: Preset name not found within published preset config (monorepo:angularmaterial). Note: this is a nested preset so please contact the preset author if you are unable to fix it yourself.

Support Webpack 4

I try to test webpack-chain with Webpack 4 one error is not valid because of Webpack 4 is no need config anymore. So not passing any config Webpack is still work. Can we remove this test?

test('validate empty', t => {
  const config = new Config();
  const errors = validateSchema(config.toConfig());
  t.is(errors.length, 1);
});

[Question] API Is very confusing

Is i have to learn webpack before use this ? I don't know what i should start with chain.
When to add, when to test, when to use, when to loader ?

Document should provide simple tutorial like webpack to make beginer approch easier

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.