GithubHelp home page GithubHelp logo

rollup / rollup-plugin-replace Goto Github PK

View Code? Open in Web Editor NEW
163.0 19.0 23.0 217 KB

This module has moved and is now available at @rollup/plugin-replace / https://github.com/rollup/plugins/blob/master/packages/replace

JavaScript 100.00%

rollup-plugin-replace's Introduction

Moved

This module has moved and is now available at @rollup/plugin-replace. Please update your dependencies. This repository is no longer maintained.

rollup-plugin-replace

Replace strings in files while bundling them.

Installation

npm install --save-dev rollup-plugin-replace

Usage

Generally, you need to ensure that rollup-plugin-replace goes before other things (like rollup-plugin-commonjs) in your plugins array, so that those plugins can apply any optimisations such as dead code removal.

// rollup.config.js
import replace from 'rollup-plugin-replace';

export default {
	// ...
	plugins: [
		replace({
			ENVIRONMENT: JSON.stringify('production')
		})
	]
};

Options

{
  // a minimatch pattern, or array of patterns, of files that
  // should be processed by this plugin (if omitted, all files
  // are included by default)...
  include: 'config.js',

  // ...and those that shouldn't, if `include` is otherwise
  // too permissive
  exclude: 'node_modules/**',

  // To replace every occurrence of `<@foo@>` instead of every
  // occurrence of `foo`, supply delimiters
  delimiters: ['<@', '@>'],

  // All other options are treated as `string: replacement`
  // replacers...
  VERSION: '1.0.0',
  ENVIRONMENT: JSON.stringify('development'),

  // or `string: (id) => replacement` functions...
  __dirname: (id) => `'${path.dirname(id)}'`,

  // ...unless you want to be careful about separating
  // values from other options, in which case you can:
  values: {
    VERSION: '1.0.0',
    ENVIRONMENT: JSON.stringify('development')
  }
}

Word boundaries

By default, values will only match if they are surrounded by word boundaries — i.e. with options like this...

{
	changed: 'replaced';
}

...and code like this...

console.log('changed');
console.log('unchanged');

...the result will be this:

console.log('replaced');
console.log('unchanged');

If that's not what you want, specify empty strings as delimiters:

{
  changed: 'replaced',
  delimiters: ['', '']
}

License

MIT

rollup-plugin-replace's People

Contributors

caccialdo avatar lukastaegert avatar mrkishi avatar nolanlawson avatar notwoods avatar rich-harris avatar shellscape avatar skalt avatar vinkla avatar wesleygrimes 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

rollup-plugin-replace's Issues

Allow async functions

Hi, I use this plugin to replace a worker with a string of its bundled source at build time. Unfortunately bundling the source of the worker is an asynchronous operation which is why I can't use this plugin without modifications.

The workaround I came up with is to add another custom plugin before this plugin in order to pause the overall execution of rollup. The custom plugin returns a promise which only gets resolved when the bundling of the worker is done. https://github.com/chrisguttandin/worker-timers/blob/2cfeb4d855c6184b54e230035c5be91be2b71c0a/config/rollup/bundle.js#L44

That all works great but it feels like a hack. I would like to propose adding support for async functions to this plugin to simplify use cases like that. I think it would be fully backwards compatible and won't introduce any breaking change.

Please let me know, if you like the idea. I'm happy to provide a pull request for it.

Plugin isn't replacing anything

Hey, I'm a bit confused about what this plugin is supposed to do. I thought I could use it to remove unoptimised code from the bundle like in Webpack but it doesn't seem to do anything for my UMD or ESM builds?

config:

const extensions = [...DEFAULT_EXTENSIONS, '.ts', '.tsx'];
const globals = {
  react: 'React',
  'react-dom': 'ReactDOM',
};
const external = Object.keys(globals);
const input = 'src/index.tsx';

const plugins = [
  replace({
    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
    ENVIRONMENT: JSON.stringify(process.env.NODE_ENV), // Tried this too
  }),
  nodeResolve({
    extensions,
    dedupe: external,
  }),
  commonjs({
    exclude: 'src/**',
  }),
  babel({
    exclude: 'node_modules/**',
    extensions,
  }),
];

export default [
  {
    input,
    output: {
      file: pkg.main,
      format: 'umd',
      name: 'flGrid',
      esModule: false,
      globals,
      sourcemap: true,
    },
    // plugins: plugins.concat(terser()),
    plugins,
    external,
  },
  {
    input,
    output: {
      file: pkg.module,
      format: 'esm',
      globals,
    },
    plugins,
    external,
  },
];

I have verified that process.env.NODE_ENV is production but if I look at the compiled code I see all the unstripped, unoptimised stuff. For example this is from Emotion the CSS lib:

Screenshot 2019-08-24 at 17 17 25

As you can see it seems that process.env.NODE_ENV hasn't been replaced and the unoptimised code is still there?

I am using the latest of all libraries as I just set this up.

Replace plugin resulting in stripping code but complaining about unused imports

I have a chunk of code along the lines of:

import myFunc from 'module-example/myFunc';

if (process.env.NODE_ENV !== 'prod') {
  something();
}

This will build fine when NODE_ENV !== prod because myFunc is used. When I set NODE_ENV to 'prod', the if statement is stripped out and the build shows the warning:

'default' is imported from external module 'module-example/myFunc' but never used.

Ideally I'd like myFunc to be removed since the import isn't needed, but this warning message makes me assume that isn't the case. Is there a better way to do this?

Can the replacement occur on the AST instead of as a string?

I know this would be a major refactoring, but the current replacing functionality breaks code that feels like it should work if coming from a webpack background:

    replace({
      values: {
        ASSET_URL: JSON.stringify('http://my-asset-url/'),
      },
    }),
// Code being transformed
Vue.prototype.ASSET_URL = ASSET_URL;

Here, both the key and the value are being replaced, resulting in a syntax error further down the build line:

Vue.prototype.'http://my-asset-url/' = 'http://my-asset-url/';

It would make sense if only identifiers are replaced, the same way webpack.DefinePlugin handles this issue.

If you feel like this would be a good change but need help implementing it, hit me up.

Can't bundle with React-Router

rollup/rollup#502

Can't bundel react-router because of

Cannot overwrite the same content twice: 'invariant'

In the other issues we found out that this is a Problem with the rollup-plugin-replace and the react-router

Nest configuration - Unexpected token

// ...
import replace from 'rollup-plugin-replace';
// ...
    replace({
      'process.env': {
        NODE_ENV: JSON.stringify(env.prod ? 'production' : 'development')
      }
    }),
// ...

rollup-plugin-hash has no effect whatsoever. WAIDW?

I'm trialing Rollup and its plugins.
My attempts to replace the string ./build/ in a manifest created by rollup-plugin-hash have no effect whatsoever. More specific, this doesn't replace anything. :

    replace({
      include: [jsManifest],
      exclude: 'node_modules/**',
      delimiters: ['',''],
      // "./build/": JSON.stringify(''),
      values: {
        "./build/": JSON.stringify(''),
        './build/': JSON.stringify(''),
        "./build/": JSON.stringify(""),
        './build/': JSON.stringify(""),
        "./build/": '',
        './build/': '',
        "./build/": "",
        './build/': "",
        build: '',
        build: "",
      }
    }),

This is the content of the manifest file ~/dev/web/rollup-with-browsersync-hash-replace/build/main.js-manifest.json :

{"./build/js/main.min.js":"./build/js/main.9bfe24db2cad759965e13900c7c5e016.min.js"}

Further, after manually removing ./build/ from the manifest file so that it becomes this, :

{"js/main.min.js":"js/main.9bfe24db2cad759965e13900c7c5e016.min.js"}

the subsequent replace also has no effect.
More specific this one :

    replace({
      include: [dist + '/**/*.html'],
      exclude: 'node_modules/**',
      values: getJsonFile(jsManifest),
    }),

This is the content of the index.html file :

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport"
        content="width=device-width,minimum-scale=1,initial-scale=1">
  <title>Testing Rollup</title>
</head>
<body>

  <h1>Testing Rollup</h1>
  <p>
    Testing <a href="http://rollupjs.org/">Rollup</a>.
  </p>

  <!-- JS bundle generated by rollup.js -->
  <script src="js/main.min.js"></script>

</body>
</html>

This is the content of my rollup.config.js file :

// Rollup plugins
import babel from 'rollup-plugin-babel';
import eslint from 'rollup-plugin-eslint';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import replace from 'rollup-plugin-replace';
import { terser } from 'rollup-plugin-terser';
import postcss from 'rollup-plugin-postcss';
import browsersync from 'rollup-plugin-browsersync'
import hash from 'rollup-plugin-hash';

// PostCSS plugins
import simplevars from 'postcss-simple-vars';
import nested from 'postcss-nested';
import presetEnv from 'postcss-preset-env';
import cssnano from 'cssnano';

import { readFileSync } from 'fs-extra';

const src = './src', dist = './build', scriptsSrc = src + '/scripts', scriptsDest = dist + '/js', stylesSrc = src + '/styles', stylesDest = dist + '/css',
  jsManifest = dist + '/main.js-manifest.json';

const getJsonFile = (file) => {
  try {
      return JSON.parse(readFileSync(file, 'utf8'));
  } catch (err) {
      if (err.code === 'ENOENT') {
        console.log('Could not find file : ' + file);
        return {};
      }
      throw err;
  }
};

export default {
  input: scriptsSrc + '/main.js',
  output: {
    file: scriptsDest + '/main.min.js',
    format: 'iife',
    sourcemap: 'inline',
  },
  watch: {
    include: src + '/**',
    exclude: 'node_modules/**',
    clearScreen: false,
  },
  plugins: [
    postcss({
      plugins: [
        simplevars(),
        nested(),
        presetEnv(),
        cssnano(),
      ],
      extensions: [ '.css' ],
    }),
    resolve({
      jsnext: true,
      main: true,
      browser: true,
    }),
    // Note that rollup-plugin-commonjs should go before other plugins that transform your modules
    // — this is to prevent other plugins from making changes that break the CommonJS detection.
    commonjs(),
    eslint({
      exclude: [
        stylesSrc + '/**',
      ]
    }),
    babel({
      exclude: 'node_modules/**',
    }),
    replace({
      exclude: 'node_modules/**',
      ENV: JSON.stringify(process.env.NODE_ENV || 'development'),
    }),
    hash({
      dest: scriptsDest + '/main.[hash:32].min.js',
      replace:true,
      algorithm: 'sha512',
      manifest: jsManifest,
    }),
    replace({
      include: [jsManifest],
      exclude: 'node_modules/**',
      delimiters: ['',''],
      // "./build/": JSON.stringify(''),
      values: {
        "./build/": JSON.stringify(''),
        './build/': JSON.stringify(''),
        "./build/": JSON.stringify(""),
        './build/': JSON.stringify(""),
        "./build/": '',
        './build/': '',
        "./build/": "",
        './build/': "",
        build: '',
        build: "",
      }
    }),
    replace({
      include: [dist + '/**/*.html'],
      exclude: 'node_modules/**',
      values: getJsonFile(jsManifest),
    }),
    (process.env.NODE_ENV === 'production' && terser()),
    browsersync({
      files: dist + '/**',
      watch: true,
      ignore: 'node_modules/**',
      server: dist + '/',
      logPrefix: 'ROLLUP',
      reloadDelay: 0,
      reloadDebounce: 0,
      reloadThrottle: 0,
      injectChanges: true,
    }),
  ],
};

Allow unmodified regexes

Hi Rich,

It looks like the handling of strings to replace doesn't work well for all cases.

For example:

replace({
    delimiters: ["", ""],
    "/* buildDev:start */[\s\S]*/* buildDev:end */": ""
}),

fails when searching for matches because the escape() function transforms the pattern to \/\* buildDev:start \*\/\[\\s\\S\]\+\/\* buildDev:end \*\/. The escaping function doesn't take into account character classes like \s or \S, whose \ character shouldn't be escaped.

In order to address this issue we have two possible solutions:

  • Creating a more complex escape() function which properly handles character classes.
  • Allowing the user to use untouched (and already escaped) regexes, that is it, apply patterns without the plugin modifying them at all –unlike it happens now, where patters are always escaped–.

If we consider the last solution –which in my opinion is the simplest and most powerful one–, the implementation of it wouldn't be much of a trouble. It would be creating a new flag of the kind unmodifiedRegexes: true on the plugin configuration and then assign the patterns unmodified to pattern around line 34.

If you agree with me this is a good idea I don't mind to make a pull request with the new feature and updated tests and docs.

File relative values

Hey folks, thanks for sharing this great plugin with us!

We've an use case where we need to replace some markups using file relative values. Perhaps, providing some constants would be a great addition to this plugin.

Example:

Constant Get replaced by
__FILE__ The current file path
__FILENAME__ The current file name
__BASEDIR__ The current base directory
{
  values: {
    PATH: '__FILE__',
    VERSION: '1.0.0',
    ENVIRONMENT: JSON.stringify( 'development' )
  }
}

Thanks in advance!

Keywords inside comments should probably not get replaced

The current behavior is that .replace replaces any instance of a certain keyword.

This is of course intended however I wonder if content inside of HTML comments <!-- --> should actually be omitted? Since you might mention a keyword in a comment to describe it's behavior.

And I might of course be wrong here, maybe there is a legitimate instance where you actually want to replace comments?

The reason I bring this up, is because this behavior happened to break my site, and it took me quite a long time to figure out the culprit. I mean logically, you would not expect a comment to have actual influence on your sites behavior. Once I figured it out it made sense, however it is not really intuitive.

So this bugreport is really just to bring this to attention. If it is actually a desired behavior be free to close this bugreport.

Run replacements after bundling

It would be nice if there was an option to run replacements after all the files were bundled/glued together.

Because of common situations like this:

import Brand from './Brand.js';

export default class BrandSubclass extends Brand {}

combined with

replace({ Brand: 'NewBrand' })

which will yield:

Could not resolve './NewBrand' from ...

edit: I guess there would be situations that could require either first or last pass replacement. Maybe { ignoreImports: true } or something of that nature could be added, but rollup resolves all of this itself, so that seems like a waste.

not working at all in ionic2 rc1

Hi,

We am not sure if we are missing something. Here is our case:

rollup.config.js:

var replace = require('rollup-plugin-replace');

.
.
.
plugins: [
builtins(),
commonjs(),
nodeResolve({
module: true,
jsnext: true,
main: true,
browser: true,
extensions: ['.js']
}),
replace({
exclude: 'node_modules/**',
include: 'src/common/apiSrv.ts',
values: {
"API_HOST": "http://192.168.1.154:8000"
}
}),
.
.
.

OR

replace({
  API_HOST: "http://192.168.1.154:8000"
  }),

apiSrv.ts:

console.log(API_HOST);

But we only got compile error. It seems the var is out of scope. We are so lost. Any ideas? ty

Option to rerun the content provider function every build

{
  //...
  watch: {
    input: [
      // ...
      './src/fileToInject.txt',
    ],
  },
  plugins: [
    // ...
    replace({
        __PLACEHOLDER__: (data) => {
          return fs.readFileSync('./src/fileToInject.txt', 'utf-8')
        },
    })
  ],
}

Expected result:

Everytime I modify fileToInject.txt, I would like my bundle to be updated with the latest content.

Current result:

Currently the function is evaluated only once at the first build. When the watcher detects a change, the bundle is rebuilt, but the replace plugin reuse the last value returned by the function. Therefore my bundle is not updated.

Solution:

Provide a evaluateEveryTime or such option.

Why is the input an object and not an array?

Seems like it would be easier to pass a 2D array rather than an Object, due to the limitation of key names:

As an Object

{
  "[a]" : 1,
  "{b}" : 2
}

As an Array

[
  ["[a]", 1],
  ["{b}", 2]
]

Seems more logical to me no? you could then also pass more settings per replacement like so:

Array with replacement settings

[
  ["[a]", 1, 'i'] // case-insensitive search
]

As an Array with Regex

[
  [/\/foo\/, '/bar/foo/', g]
]

Regular expression syntax

If you use regular expression syntax in the search patterns, you quickly start getting undefined values back as replacements. It's crafty to use a single RegExp and use the patterns as keys to store the replacements, but the returned matches don't necessarily equal the patterns unless they are simple strings. As an example which bit me: searching for require('path') requires escaping the parens and quotes, but then the replacement is stored under a key like 'require\\(\'path\'\\)' when the match returned is simply require('path'), which isn't a key in values.

I searched for a way to find out what part of the alternation pattern was matched, but I couldn't find anything easy. Otherwise I would have submitted a fix. Maybe using named groups (e.g. https://github.com/edvinv/named-js-regexp) or simply using multiple regular expressions would work. The latter might be slower, but more straightforward.

Or disallow regular expressions and remove any escape sequences in the keys. But that wouldn't be as potentially useful!

mixed-typed property names (some with delimiters)

How can I do mixed replace? (some variables have delimiters and some don't:

replace({
    "delimiters" : [ '[', ']' ],
    "SERVERPATH" : JSON.stringify(config.serverPath),   // <---- requires delimiters
    "prodUrl"    : JSON.stringify(config.prodUrl),      // <---- requires delimiters
    "mocks/"     : JSON.stringify(config.serverPath + '/mocks/') 
})

It was an utter failure to not use the delimiters key and trying to manually write [SERVERPATH] as key name. I also tried to escape the key like \[SERVERPATH\] without output success .

include and exclude are literally replaced also

Not sure if I'm using it right but, this...

        replace({
            exclude: 'node_modules/**',
            ENV: JSON.stringify(process.env.NODE_ENV || 'production'),
        }),

replaces any occurrence of exclude is replace with node_modules/**

Suggested fix...

	var pattern = new RegExp( delimiters[0]
		+ '(' + Object.keys( values ).filter( p =>
			(p !== 'include') && (p !== 'exclude')
		).join( '|' ) + ')'
		+ delimiters[1], 'g' );

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.