I'm using Symfony 3.3 and the assetic bundle. I have this in my config.yml:
assetic:
debug: '%kernel.debug%'
use_controller: '%kernel.debug%'
filters:
cssrewrite: ~
typescript:
bin: "%kernel.root_dir%/../node_modules/typescript/bin/tsc"
apply_to: "\\.ts$"
When I try to compile my TypeScript files, I get this error:
Output:
../../../../private/var/folders/94/45yn02792ksfglm12pjxxlp00000gn/T/assetic_typescript_in59bccf08e6357/my-form.ts.ts(6,1): error TS6131: Cannot compile modules using option 'out' unless the '--module' flag is 'amd' or 'system'.
../../../../private/var/folders/94/45yn02792ksfglm12pjxxlp00000gn/T/assetic_typescript_in59bccf08e6357/my-form.ts.ts(6,22): error TS2307: Cannot find module './my-obj.model'.
This occurs after I use an import statements like import { Obj } from './my-obj.model';
. If I don't use import statements, ts compilation works fine.
How do I add give assetic's TypeScript filter either a --module system
parameter or a tsconfig.json
?
error TS6131: Cannot compile modules using option 'out' unless the '--module' flag is 'amd' or 'system'.
Extra options for tsc
command through AsseticBundle
is not possible at the moment.
error TS2307: Cannot find module './model'.
and here AsseticBundle
save each individual ts
file into a tmp dir/file to compile it, so it doesn't support this feature either.
The good news is that you can override the behavior of the assetic.filter.typescript
service to fix it. Let's add this class to the application:
namespace AppBundle\Assetic\Filter;
use Assetic\Asset\AssetInterface;
use Assetic\Exception\FilterException;
use Assetic\Util\FilesystemUtils;
class TypeScriptFilter extends \Assetic\Filter\TypeScriptFilter
{
private $tscBin;
private $nodeBin;
public function __construct($tscBin = '/usr/bin/tsc', $nodeBin = null)
{
$this->tscBin = $tscBin;
$this->nodeBin = $nodeBin;
}
public function filterLoad(AssetInterface $asset)
{
$pb = $this->createProcessBuilder($this->nodeBin
? array($this->nodeBin, $this->tscBin)
: array($this->tscBin));
// using source path to compile and allow "imports".
$inputPath = $asset->getSourceRoot().DIRECTORY_SEPARATOR.$asset->getSourcePath();
$outputPath = FilesystemUtils::createTemporaryFile('typescript_out');
$pb
->add($inputPath)
// passing the required options here
->add('--module')->add('system')
->add('--out')
->add($outputPath)
;
$proc = $pb->getProcess();
$code = $proc->run();
if (0 !== $code) {
if (file_exists($outputPath)) {
unlink($outputPath);
}
throw FilterException::fromProcess($proc)->setInput($asset->getContent());
}
if (!file_exists($outputPath)) {
throw new \RuntimeException('Error creating output file.');
}
$compiledJs = file_get_contents($outputPath);
unlink($outputPath);
$asset->setContent($compiledJs);
}
}
Then, change the value of the parameter class to override the original service:
# app/config/services.yml
parameters:
assetic.filter.typescript.class: 'AppBundle\Assetic\Filter\TypeScriptFilter'
It worked for me with your assetic
configuration.
In the other hand, the new recommended way to manage assets for Symfony applications: Webpack Encore giving you a clean & powerful API for bundling JavaScript modules, pre-processing CSS & JS and compiling and minifying assets, with support for TypeScript loader.
Just add it to tsc bin path, should do the hack :)
assetic:
debug: '%kernel.debug%'
use_controller: '%kernel.debug%'
filters:
cssrewrite: ~
typescript:
bin: "%kernel.root_dir%/../node_modules/typescript/bin/tsc --module system"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With