How to get the file-path of the currently executing javascript code
Asked Answered
C

13

88

I'm trying to do something like a C #include "filename.c", or PHP include(dirname(__FILE__)."filename.php") but in javascript. I know I can do this if I can get the URL a js file was loaded from (e.g. the URL given in the src attribute of the tag). Is there any way for the javascript to know that?

Alternatively, is there any good way to load javascript dynamically from the same domain (without knowing the domain specifically)? For example, lets say we have two identical servers (QA and production) but they clearly have different URL domains. Is there a way to do something like include("myLib.js"); where myLib.js will load from the domain of the file loading it?

Sorry if thats worded a little confusingly.

Counterintelligence answered 12/2, 2010 at 23:0 Comment(0)
T
93

Within the script:

var scripts = document.getElementsByTagName("script"),
    src = scripts[scripts.length-1].src;

This works because the browser loads and executes scripts in order, so while your script is executing, the document it was included in is sure to have your script element as the last one on the page. This code of course must be 'global' to the script, so save src somewhere where you can use it later. Avoid leaking global variables by wrapping it in:

(function() { ... })();
Twigg answered 12/2, 2010 at 23:8 Comment(12)
This is a great suggestion, as long as the code in the script is run "inline" (i.e. in a global context or "immediate run anonymous method", as you've suggested, and not in a "called later" function or set-timeout). You could create a var in each javascript for the current file/path in this way. Careful however, "leaking global variables" cannot be solved by what I've called immediate-run-anon-methods, (function(){...})(); - your example above will still create a global var called src because it does not have a var specifier before itBondie
That is pretty brilliant. One problem is that if I use jquery's getScript method, it fails (returns blank). Any solution to that?Counterintelligence
There is a var specifier for 'src' (see comma on end of the first line)Twigg
@B T: don't use jQuery. :) Ooops, just kidding!Schoolbook
@InifinitesLoop: in a similar answer to a similar question they suggest to return scripts[scripts.length-1].getAttribute('src', -1), see more here: https://mcmap.net/q/95184/-what-is-my-script-src-url/…Schoolbook
The issue of whether the url is resolved or not doesn't usually matter, since you'd probably want your code to work no matter how the 'src' attribute is specified. And whatever the value is, if you're using it in the same page context it came from, it will do the right thing.Twigg
@B T: beaware that InifinitesLoop code might return script src as a relative path on IE 6/7 (i.e. '/path/script.js') and the same script src as a full http path on IE8 / FF / Chrome / Safari (i.e. 'domain.com/path/script.js'). The code here is more cross-browser: https://mcmap.net/q/95184/-what-is-my-script-src-url/…Schoolbook
This approach has served me well in many cases. Getting my own script path while inside of a Web Worker is not among them.Transpire
@Transpire See my very recent answer below. Getting the file name from the stacktrace using the stackinfo module (github) might help you.Counterintelligence
The accepted answer here was not working for me because it was conflicting with inline scripts a document. To avoid this I wrote the function below to target <script> tags with a [src] attribute only.Pod
This doesn't work if your <script> tag isn't the last one due to various reasons, e.g. if you dynamically inject that tag via JS at the start of <head>. See also this comment.Prearrange
This won't work also if the script was added to the page with async and defer.Clara
A
69

All browsers except Internet Explorer (any version) have document.currentScript, which always works always (no matter how the file was included (async, bookmarklet etc)).

If you want to know the full URL of the JS file you're in right now:

var script = document.currentScript;
var fullUrl = script.src;

Tadaa.

Astrology answered 25/10, 2013 at 12:9 Comment(3)
This is awesome and exactly what I was hoping to find!Gallinule
I think it's good to know - if object is initialized outside from that file script, then that path is differet - so if someone want path of script it have to be called in root of that file scriptDovelike
This doesn't work in modules.Louis
C
29

I just made this little trick :

window.getRunningScript = () => {
    return () => {      
        return new Error().stack.match(/([^ \n])*([a-z]*:\/\/\/?)*?[a-z0-9\/\\]*\.js/ig)[0]
    }
}
console.log('%c Currently running script:', 'color: blue', getRunningScript()())

screenshot

Works on: Chrome, Firefox, Edge, Opera

Enjoy !

Capers answered 4/3, 2017 at 10:23 Comment(2)
This is great! I was having an issue because my javascript file is being inserted via a chrome extension and not through conventional means. Looking at document.currentScript.src and looking at the previously added <script> was coming up empty. This totally worked.Burra
Also, I've I've never seen that color trick in console.log before. Very cool.Burra
P
18

The accepted answer here does not work if you have inline scripts in your document. To avoid this you can use the following to only target <script> tags with a [src] attribute.

/**
 * Current Script Path
 *
 * Get the dir path to the currently executing script file
 * which is always the last one in the scripts array with
 * an [src] attr
 */
var currentScriptPath = function () {

    var scripts = document.querySelectorAll( 'script[src]' );
    var currentScript = scripts[ scripts.length - 1 ].src;
    var currentScriptChunks = currentScript.split( '/' );
    var currentScriptFile = currentScriptChunks[ currentScriptChunks.length - 1 ];

    return currentScript.replace( currentScriptFile, '' );
}

This effectively captures the last external .js file, solving some issues I encountered with inline JS templates.

Pod answered 24/9, 2014 at 17:40 Comment(1)
Works great!!!. Thank you!!!. I've found and tried a lots of solutions without a positive result.Tula
M
9

Refining upon the answers found here I came up with the following:

getCurrentScript.js

var getCurrentScript = function() {
  if (document.currentScript) {
    return document.currentScript.src;
  } else {
    var scripts = document.getElementsByTagName('script');
    return scripts[scripts.length - 1].src;
  }
}

// module.exports = getCurrentScript;
console.log({log: getCurrentScript()})

getCurrentScriptPath.js

var getCurrentScript = require('./getCurrentScript');

var getCurrentScriptPath = function () {
  var script = getCurrentScript();
  var path = script.substring(0, script.lastIndexOf('/'));
  return path;
};

module.exports = getCurrentScriptPath;

BTW: I'm using CommonJS module format and bundling with webpack.

Montana answered 9/12, 2014 at 1:25 Comment(0)
C
5

I've more recently found a much cleaner approach to this, which can be executed at any time, rather than being forced to do it synchronously when the script loads.

Use stackinfo to get a stacktrace at a current location, and grab the info.file name off the top of the stack.

info = stackinfo()
console.log('This is the url of the script '+info[0].file)
Counterintelligence answered 5/5, 2014 at 0:28 Comment(0)
M
3

I've coded a simple function which allows to get the absolute location of the current javascript file, by using a try/catch method.

// Get script file location
// doesn't work for older browsers

var getScriptLocation = function() {
    var fileName    = "fileName";
    var stack       = "stack";
    var stackTrace  = "stacktrace";
    var loc     = null;

    var matcher = function(stack, matchedLoc) { return loc = matchedLoc; };

    try { 

        // Invalid code
        0();

    }  catch (ex) {

        if(fileName in ex) { // Firefox
            loc = ex[fileName];
        } else if(stackTrace in ex) { // Opera
            ex[stackTrace].replace(/called from line \d+, column \d+ in (.*):/gm, matcher);
        } else if(stack in ex) { // WebKit, Blink and IE10
            ex[stack].replace(/at.*?\(?(\S+):\d+:\d+\)?$/g, matcher);
        }

        return loc;
    }

};

You can see it here.

Macleod answered 11/10, 2014 at 21:35 Comment(5)
Why down vote? Consider adding a comment as well.. Anyways.Macleod
Because according to the rules you are supposed to explain the solution in your answer, not just link. If that link dies then your answer is meaningless.Hostess
This is awesome, thanks for sharing. Also, you could do a check for document.currentScript just in case it is defined.Schaffhausen
You should copy that small solution from the github to here (You can leave the link in for the newest version) so it doesn't become obsolete when you delete or replace the github project (again)Hacienda
For me it gets the first script, not where it's called.Scribble
H
3

Refining upon the answers found here:

little trick

getCurrentScript and getCurrentScriptPath

I came up with the following:

//Thanks to https://mcmap.net/q/236719/-how-to-get-the-file-path-of-the-currently-executing-javascript-code
var getCurrentScript = function() {

  if (document.currentScript && (document.currentScript.src !== ''))
    return document.currentScript.src;
  var scripts = document.getElementsByTagName('script'),
    str = scripts[scripts.length - 1].src;
  if (str !== '')
    return str ;
  //Thanks to https://mcmap.net/q/236719/-how-to-get-the-file-path-of-the-currently-executing-javascript-code
  return new Error().stack.match(/(https?:[^:]*)/)[0];

};

//Thanks to https://mcmap.net/q/236719/-how-to-get-the-file-path-of-the-currently-executing-javascript-code
var getCurrentScriptPath = function() {
  var script = getCurrentScript(),
    path = script.substring(0, script.lastIndexOf('/'));
  return path;
};

console.log({path: getCurrentScriptPath()})
Higgins answered 1/3, 2020 at 1:20 Comment(0)
G
1

I may be misunderstanding your question but it seems you should just be able to use a relative path as long as the production and development servers use the same path structure.

<script language="javascript" src="js/myLib.js" />
Gaff answered 12/2, 2010 at 23:6 Comment(5)
The problem is that this javascript library is meant to be loaded on different domains.Counterintelligence
So is this a single js library file located on one domain that needs to be pulled in across multiple domains? Or is this a js file that resides on multiple domains that need to pull in other js files relative to its source? Could you provide an example of what you are trying to accomplish?Gaff
Its both actually. The js file will reside on multiple domains (QA vs production), and it will also be included from multiple domains (whatever web app needs to use the library).Counterintelligence
This may be what you're trying to get around, but could you hardcode the path of the script as a variable and have devel and production versions of your lib that have that line being their only difference? Or more simply pass something to a single script as a get param that specifies its location: ?devel=trueGaff
That is what I'm trying to avoid. I'm also trying to avoid a GET parameter, but thats a perfectly valid solution. I'm just too lazy to much around in all our Java Struts stuff for this. : )Counterintelligence
B
1

Regardless of whether its a script, a html file (for a frame, for example), css file, image, whatever, if you dont specify a server/domain the path of the html doc will be the default, so you could do, for example,

<script type=text/javascript src='/dir/jsfile.js'></script>

or

<script type=text/javascript src='../../scripts/jsfile.js'></script>

If you don't provide the server/domain, the path will be relative to either the path of the page or script of the main document's path

Bondie answered 12/2, 2010 at 23:6 Comment(0)
T
1

I've thrown together some spaghetti code that will get the current .js file ran (ex. if you run a script with "node ." you can use this to get the directory of the script that's running)

this gets it as "file://path/to/directoryWhere/fileExists"

var thisFilesDirectoryPath = stackinfo()[0].traceline.substring("readFile (".length, stackinfo()[0].traceline.length - ")".length-"readFile (".length);

this requires an npm package (im sure its on other platforms as well):

npm i stackinfo

import stackinfo from 'stackinfo'; or var {stackinfo} = require("stackinfo");

Truman answered 18/5, 2022 at 1:56 Comment(3)
With node you can just use __dirname. My question was really about browser js.Counterintelligence
@BT not always - i made this because for some reason __dirname didn't exist in my project.Truman
You might have been using es6 modules, which for some reason gets rid of it. This brings it back: ``` const __filename = url.fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); ```Counterintelligence
U
0
function getCurrnetScriptName() {
    const url = new URL(document.currentScript.src);
    const {length:len, [len-1]:last} = url.pathname.split('/');
    return last.slice(0,-3);
}
Uncanonical answered 3/6, 2021 at 9:12 Comment(0)
M
0

In an ES6 module environment, the URL of the currently executing module can be obtained from 'import.meta' property. Refer MDN Document.

Also refer document.currentScript is null (Don Park's answer)

Below is an example:

//generalTests.mjs
getLocation();
function getLocation(){

    console.log("Current script location --->>> "+import.meta.url);

}

The above is being used in a module environment, where the module is being loaded in HTML script element

<body>
    <script type="module" src="generalTests.mjs"></script>
</body>

The console output is as follows: console output

Magnesia answered 25/2, 2024 at 6:40 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.