rollup / rollup-plugin-replace Goto Github PK
View Code? Open in Web Editor NEWThis module has moved and is now available at @rollup/plugin-replace / https://github.com/rollup/plugins/blob/master/packages/replace
This module has moved and is now available at @rollup/plugin-replace / https://github.com/rollup/plugins/blob/master/packages/replace
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:
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.
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.
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' );
I have this:
plugins: [
replace({
'NODE_ENV': process.env.NODE_ENV
}),
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?
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!
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.
// ...
import replace from 'rollup-plugin-replace';
// ...
replace({
'process.env': {
NODE_ENV: JSON.stringify(env.prod ? 'production' : 'development')
}
}),
// ...
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 .
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
Seems like it would be easier to pass a 2D array rather than an Object, due to the limitation of key names:
{
"[a]" : 1,
"{b}" : 2
}
[
["[a]", 1],
["{b}", 2]
]
Seems more logical to me no? you could then also pass more settings per replacement like so:
[
["[a]", 1, 'i'] // case-insensitive search
]
[
[/\/foo\/, '/bar/foo/', g]
]
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.
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,
}),
],
};
用AST进行替换,更加灵活
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.
Anything native with dotenv (https://github.com/motdotla/dotenv)?
{
//...
watch: {
input: [
// ...
'./src/fileToInject.txt',
],
},
plugins: [
// ...
replace({
__PLACEHOLDER__: (data) => {
return fs.readFileSync('./src/fileToInject.txt', 'utf-8')
},
})
],
}
Everytime I modify fileToInject.txt
, I would like my bundle to be updated with the latest content.
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.
Provide a evaluateEveryTime
or such option.
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:
escape()
function which properly handles character classes.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.
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
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!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.